зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1446203 - Basic Payment Request Shipping Address Add/Edit page. r=MattN
MozReview-Commit-ID: 9f0vPciw65V --HG-- rename : toolkit/components/payments/res/containers/basic-card-form.js => toolkit/components/payments/res/containers/address-form.js rename : toolkit/components/payments/test/browser/browser_card_edit.js => toolkit/components/payments/test/browser/browser_address_edit.js rename : toolkit/components/payments/test/mochitest/test_basic_card_form.html => toolkit/components/payments/test/mochitest/test_address_form.html extra : rebase_source : 6f0e2ba44dbe5a560e7f3bcb4f533cc32a5abc57
This commit is contained in:
Родитель
2d7d260a1e
Коммит
9963ec2b5f
|
@ -144,6 +144,8 @@ update.locale
|
||||||
browser/chrome/browser/content/branding/icon128.png
|
browser/chrome/browser/content/branding/icon128.png
|
||||||
browser/chrome/devtools/content/framework/dev-edition-promo/dev-edition-logo.png
|
browser/chrome/devtools/content/framework/dev-edition-promo/dev-edition-logo.png
|
||||||
# Bug 1451016 - Nightly-only PaymentRequest & Form Autofill code sharing.
|
# Bug 1451016 - Nightly-only PaymentRequest & Form Autofill code sharing.
|
||||||
|
browser/features/formautofill@mozilla.org/chrome/content/editAddress.xhtml
|
||||||
|
chrome/toolkit/res/payments/formautofill/editAddress.xhtml
|
||||||
browser/features/formautofill@mozilla.org/chrome/content/editCreditCard.xhtml
|
browser/features/formautofill@mozilla.org/chrome/content/editCreditCard.xhtml
|
||||||
chrome/toolkit/res/payments/formautofill/editCreditCard.xhtml
|
chrome/toolkit/res/payments/formautofill/editCreditCard.xhtml
|
||||||
browser/features/formautofill@mozilla.org/chrome/content/autofillEditForms.js
|
browser/features/formautofill@mozilla.org/chrome/content/autofillEditForms.js
|
||||||
|
|
|
@ -65,7 +65,11 @@ let PaymentFrameScript = {
|
||||||
* Expose privileged utility functions to the unprivileged page.
|
* Expose privileged utility functions to the unprivileged page.
|
||||||
*/
|
*/
|
||||||
exposeUtilityFunctions() {
|
exposeUtilityFunctions() {
|
||||||
|
let waivedContent = Cu.waiveXrays(content);
|
||||||
let PaymentDialogUtils = {
|
let PaymentDialogUtils = {
|
||||||
|
DEFAULT_REGION: FormAutofillUtils.DEFAULT_REGION,
|
||||||
|
supportedCountries: FormAutofillUtils.supportedCountries,
|
||||||
|
|
||||||
getAddressLabel(address) {
|
getAddressLabel(address) {
|
||||||
return FormAutofillUtils.getAddressLabel(address);
|
return FormAutofillUtils.getAddressLabel(address);
|
||||||
},
|
},
|
||||||
|
@ -73,8 +77,12 @@ let PaymentFrameScript = {
|
||||||
isCCNumber(value) {
|
isCCNumber(value) {
|
||||||
return FormAutofillUtils.isCCNumber(value);
|
return FormAutofillUtils.isCCNumber(value);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getFormFormat(country) {
|
||||||
|
let format = FormAutofillUtils.getFormFormat(country);
|
||||||
|
return Cu.cloneInto(format, waivedContent);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
let waivedContent = Cu.waiveXrays(content);
|
|
||||||
waivedContent.PaymentDialogUtils = Cu.cloneInto(PaymentDialogUtils, waivedContent, {
|
waivedContent.PaymentDialogUtils = Cu.cloneInto(PaymentDialogUtils, waivedContent, {
|
||||||
cloneFunctions: true,
|
cloneFunctions: true,
|
||||||
});
|
});
|
||||||
|
|
|
@ -19,6 +19,7 @@ toolkit.jar:
|
||||||
res/payments/debugging.html (res/debugging.html)
|
res/payments/debugging.html (res/debugging.html)
|
||||||
res/payments/debugging.js (res/debugging.js)
|
res/payments/debugging.js (res/debugging.js)
|
||||||
res/payments/formautofill/autofillEditForms.js (../../../browser/extensions/formautofill/content/autofillEditForms.js)
|
res/payments/formautofill/autofillEditForms.js (../../../browser/extensions/formautofill/content/autofillEditForms.js)
|
||||||
|
res/payments/formautofill/editAddress.xhtml (../../../browser/extensions/formautofill/content/editAddress.xhtml)
|
||||||
res/payments/formautofill/editCreditCard.xhtml (../../../browser/extensions/formautofill/content/editCreditCard.xhtml)
|
res/payments/formautofill/editCreditCard.xhtml (../../../browser/extensions/formautofill/content/editCreditCard.xhtml)
|
||||||
res/payments/unprivileged-fallbacks.js (res/unprivileged-fallbacks.js)
|
res/payments/unprivileged-fallbacks.js (res/unprivileged-fallbacks.js)
|
||||||
res/payments/mixins/ (res/mixins/*.js)
|
res/payments/mixins/ (res/mixins/*.js)
|
||||||
|
|
|
@ -0,0 +1,151 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* 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/. */
|
||||||
|
|
||||||
|
/* import-globals-from ../../../../../browser/extensions/formautofill/content/autofillEditForms.js*/
|
||||||
|
import PaymentStateSubscriberMixin from "../mixins/PaymentStateSubscriberMixin.js";
|
||||||
|
import paymentRequest from "../paymentRequest.js";
|
||||||
|
/* import-globals-from ../unprivileged-fallbacks.js */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <address-form></address-form>
|
||||||
|
*
|
||||||
|
* XXX: Bug 1446164 - This form isn't localized when used via this custom element
|
||||||
|
* as it will be much easier to share the logic once we switch to Fluent.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default class AddressForm extends PaymentStateSubscriberMixin(HTMLElement) {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.genericErrorText = document.createElement("div");
|
||||||
|
|
||||||
|
this.backButton = document.createElement("button");
|
||||||
|
this.backButton.addEventListener("click", this);
|
||||||
|
|
||||||
|
this.saveButton = document.createElement("button");
|
||||||
|
this.saveButton.addEventListener("click", this);
|
||||||
|
|
||||||
|
// The markup is shared with form autofill preferences.
|
||||||
|
let url = "formautofill/editAddress.xhtml";
|
||||||
|
this.promiseReady = this._fetchMarkup(url).then(doc => {
|
||||||
|
this.form = doc.getElementById("form");
|
||||||
|
return this.form;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_fetchMarkup(url) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let xhr = new XMLHttpRequest();
|
||||||
|
xhr.responseType = "document";
|
||||||
|
xhr.addEventListener("error", reject);
|
||||||
|
xhr.addEventListener("load", evt => {
|
||||||
|
resolve(xhr.response);
|
||||||
|
});
|
||||||
|
xhr.open("GET", url);
|
||||||
|
xhr.send();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
connectedCallback() {
|
||||||
|
this.promiseReady.then(form => {
|
||||||
|
this.appendChild(form);
|
||||||
|
|
||||||
|
let record = {};
|
||||||
|
this.formHandler = new EditAddress({
|
||||||
|
form,
|
||||||
|
}, record, {
|
||||||
|
DEFAULT_REGION: PaymentDialogUtils.DEFAULT_REGION,
|
||||||
|
getFormFormat: PaymentDialogUtils.getFormFormat,
|
||||||
|
supportedCountries: PaymentDialogUtils.supportedCountries,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.appendChild(this.genericErrorText);
|
||||||
|
this.appendChild(this.backButton);
|
||||||
|
this.appendChild(this.saveButton);
|
||||||
|
// Only call the connected super callback(s) once our markup is fully
|
||||||
|
// connected, including the shared form fetched asynchronously.
|
||||||
|
super.connectedCallback();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render(state) {
|
||||||
|
this.backButton.textContent = this.dataset.backButtonLabel;
|
||||||
|
this.saveButton.textContent = this.dataset.saveButtonLabel;
|
||||||
|
|
||||||
|
let record = {};
|
||||||
|
let {
|
||||||
|
page,
|
||||||
|
savedAddresses,
|
||||||
|
} = state;
|
||||||
|
|
||||||
|
this.genericErrorText.textContent = page.error;
|
||||||
|
|
||||||
|
let editing = !!page.guid;
|
||||||
|
|
||||||
|
// If an address is selected we want to edit it.
|
||||||
|
if (editing) {
|
||||||
|
record = savedAddresses[page.guid];
|
||||||
|
if (!record) {
|
||||||
|
throw new Error("Trying to edit a non-existing address: " + page.guid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.formHandler.loadRecord(record);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleEvent(event) {
|
||||||
|
switch (event.type) {
|
||||||
|
case "click": {
|
||||||
|
this.onClick(event);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onClick(evt) {
|
||||||
|
switch (evt.target) {
|
||||||
|
case this.backButton: {
|
||||||
|
this.requestStore.setState({
|
||||||
|
page: {
|
||||||
|
id: "payment-summary",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case this.saveButton: {
|
||||||
|
this.saveRecord();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
throw new Error("Unexpected click target");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
saveRecord() {
|
||||||
|
let record = this.formHandler.buildFormObject();
|
||||||
|
let {
|
||||||
|
page,
|
||||||
|
selectedStateKey,
|
||||||
|
} = this.requestStore.getState();
|
||||||
|
|
||||||
|
paymentRequest.updateAutofillRecord("addresses", record, page.guid, {
|
||||||
|
errorStateChange: {
|
||||||
|
page: {
|
||||||
|
id: "address-page",
|
||||||
|
error: this.dataset.errorGenericSave,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
preserveOldProperties: true,
|
||||||
|
selectedStateKey,
|
||||||
|
successStateChange: {
|
||||||
|
page: {
|
||||||
|
id: "payment-summary",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("address-form", AddressForm);
|
|
@ -8,7 +8,7 @@ import RichSelect from "../components/rich-select.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <address-picker></address-picker>
|
* <address-picker></address-picker>
|
||||||
* Container around <rich-select> (eventually providing add/edit links) with
|
* Container around add/edit links and <rich-select> with
|
||||||
* <address-option> listening to savedAddresses.
|
* <address-option> listening to savedAddresses.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -21,10 +21,21 @@ export default class AddressPicker extends PaymentStateSubscriberMixin(HTMLEleme
|
||||||
super();
|
super();
|
||||||
this.dropdown = new RichSelect();
|
this.dropdown = new RichSelect();
|
||||||
this.dropdown.addEventListener("change", this);
|
this.dropdown.addEventListener("change", this);
|
||||||
|
this.addLink = document.createElement("a");
|
||||||
|
this.addLink.href = "javascript:void(0)";
|
||||||
|
this.addLink.textContent = this.dataset.addLinkLabel;
|
||||||
|
this.addLink.addEventListener("click", this);
|
||||||
|
this.editLink = document.createElement("a");
|
||||||
|
this.editLink.href = "javascript:void(0)";
|
||||||
|
this.editLink.textContent = this.dataset.editLinkLabel;
|
||||||
|
this.editLink.addEventListener("click", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
connectedCallback() {
|
connectedCallback() {
|
||||||
this.appendChild(this.dropdown);
|
this.appendChild(this.dropdown);
|
||||||
|
this.appendChild(this.addLink);
|
||||||
|
this.append(" ");
|
||||||
|
this.appendChild(this.editLink);
|
||||||
super.connectedCallback();
|
super.connectedCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,6 +145,9 @@ export default class AddressPicker extends PaymentStateSubscriberMixin(HTMLEleme
|
||||||
this.onChange(event);
|
this.onChange(event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "click": {
|
||||||
|
this.onClick(event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,6 +160,33 @@ export default class AddressPicker extends PaymentStateSubscriberMixin(HTMLEleme
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onClick({target}) {
|
||||||
|
let nextState = {
|
||||||
|
page: {
|
||||||
|
id: "address-page",
|
||||||
|
selectedStateKey: this.selectedStateKey,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (target) {
|
||||||
|
case this.addLink: {
|
||||||
|
nextState.page.guid = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case this.editLink: {
|
||||||
|
let state = this.requestStore.getState();
|
||||||
|
let selectedAddressGUID = state[this.selectedStateKey];
|
||||||
|
nextState.page.guid = selectedAddressGUID;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
throw new Error("Unexpected onClick");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.requestStore.setState(nextState);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
customElements.define("address-picker", AddressPicker);
|
customElements.define("address-picker", AddressPicker);
|
||||||
|
|
|
@ -9,6 +9,7 @@ import paymentRequest from "../paymentRequest.js";
|
||||||
|
|
||||||
import "../components/currency-amount.js";
|
import "../components/currency-amount.js";
|
||||||
import "./address-picker.js";
|
import "./address-picker.js";
|
||||||
|
import "./address-form.js";
|
||||||
import "./basic-card-form.js";
|
import "./basic-card-form.js";
|
||||||
import "./order-details.js";
|
import "./order-details.js";
|
||||||
import "./payment-method-picker.js";
|
import "./payment-method-picker.js";
|
||||||
|
|
|
@ -13,8 +13,12 @@
|
||||||
<!ENTITY pickupAddressLabel "Pickup Address">
|
<!ENTITY pickupAddressLabel "Pickup Address">
|
||||||
<!ENTITY shippingOptionsLabel "Shipping Options">
|
<!ENTITY shippingOptionsLabel "Shipping Options">
|
||||||
<!ENTITY paymentMethodsLabel "Payment Method">
|
<!ENTITY paymentMethodsLabel "Payment Method">
|
||||||
|
<!ENTITY address.addLink.label "Add">
|
||||||
|
<!ENTITY address.editLink.label "Edit">
|
||||||
<!ENTITY basicCard.addLink.label "Add">
|
<!ENTITY basicCard.addLink.label "Add">
|
||||||
<!ENTITY basicCard.editLink.label "Edit">
|
<!ENTITY basicCard.editLink.label "Edit">
|
||||||
|
<!ENTITY payer.addLink.label "Add">
|
||||||
|
<!ENTITY payer.editLink.label "Edit">
|
||||||
<!ENTITY payerLabel "Contact Information">
|
<!ENTITY payerLabel "Contact Information">
|
||||||
<!ENTITY cancelPaymentButton.label "Cancel">
|
<!ENTITY cancelPaymentButton.label "Cancel">
|
||||||
<!ENTITY approvePaymentButton.label "Pay">
|
<!ENTITY approvePaymentButton.label "Pay">
|
||||||
|
@ -28,6 +32,9 @@
|
||||||
<!ENTITY basicCardPage.backButton.label "Back">
|
<!ENTITY basicCardPage.backButton.label "Back">
|
||||||
<!ENTITY basicCardPage.saveButton.label "Save">
|
<!ENTITY basicCardPage.saveButton.label "Save">
|
||||||
<!ENTITY basicCardPage.persistCheckbox.label "Save credit card to Firefox (Security code will not be saved)">
|
<!ENTITY basicCardPage.persistCheckbox.label "Save credit card to Firefox (Security code will not be saved)">
|
||||||
|
<!ENTITY addressPage.error.genericSave "There was an error saving the address.">
|
||||||
|
<!ENTITY addressPage.backButton.label "Back">
|
||||||
|
<!ENTITY addressPage.saveButton.label "Save">
|
||||||
]>
|
]>
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
<head>
|
<head>
|
||||||
|
@ -75,7 +82,10 @@
|
||||||
data-shipping-address-label="&shippingAddressLabel;"
|
data-shipping-address-label="&shippingAddressLabel;"
|
||||||
data-delivery-address-label="&deliveryAddressLabel;"
|
data-delivery-address-label="&deliveryAddressLabel;"
|
||||||
data-pickup-address-label="&pickupAddressLabel;"><label></label></div>
|
data-pickup-address-label="&pickupAddressLabel;"><label></label></div>
|
||||||
<address-picker class="shipping-related" selected-state-key="selectedShippingAddress"></address-picker>
|
<address-picker class="shipping-related"
|
||||||
|
data-add-link-label="&address.addLink.label;"
|
||||||
|
data-edit-link-label="&address.editLink.label;"
|
||||||
|
selected-state-key="selectedShippingAddress"></address-picker>
|
||||||
|
|
||||||
<div class="shipping-related"><label>&shippingOptionsLabel;</label></div>
|
<div class="shipping-related"><label>&shippingOptionsLabel;</label></div>
|
||||||
<shipping-option-picker class="shipping-related"></shipping-option-picker>
|
<shipping-option-picker class="shipping-related"></shipping-option-picker>
|
||||||
|
@ -88,6 +98,8 @@
|
||||||
|
|
||||||
<div class="payer-related"><label>&payerLabel;</label></div>
|
<div class="payer-related"><label>&payerLabel;</label></div>
|
||||||
<address-picker class="payer-related"
|
<address-picker class="payer-related"
|
||||||
|
data-add-link-label="&payer.addLink.label;"
|
||||||
|
data-edit-link-label="&payer.editLink.label;"
|
||||||
selected-state-key="selectedPayerAddress"></address-picker>
|
selected-state-key="selectedPayerAddress"></address-picker>
|
||||||
<div id="error-text"></div>
|
<div id="error-text"></div>
|
||||||
</section>
|
</section>
|
||||||
|
@ -114,6 +126,13 @@
|
||||||
data-save-button-label="&basicCardPage.saveButton.label;"
|
data-save-button-label="&basicCardPage.saveButton.label;"
|
||||||
data-persist-checkbox-label="&basicCardPage.persistCheckbox.label;"
|
data-persist-checkbox-label="&basicCardPage.persistCheckbox.label;"
|
||||||
hidden="hidden"></basic-card-form>
|
hidden="hidden"></basic-card-form>
|
||||||
|
|
||||||
|
<address-form id="address-page"
|
||||||
|
class="page"
|
||||||
|
data-error-generic-save="&addressPage.error.genericSave;"
|
||||||
|
data-back-button-label="&addressPage.backButton.label;"
|
||||||
|
data-save-button-label="&addressPage.saveButton.label;"
|
||||||
|
hidden="hidden"></address-form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="disabled-overlay" hidden="hidden">
|
<div id="disabled-overlay" hidden="hidden">
|
||||||
|
|
|
@ -28,4 +28,20 @@ var PaymentDialogUtils = {
|
||||||
isCCNumber(str) {
|
isCCNumber(str) {
|
||||||
return str.length > 0;
|
return str.length > 0;
|
||||||
},
|
},
|
||||||
|
DEFAULT_REGION: "US",
|
||||||
|
supportedCountries: ["US", "CA"],
|
||||||
|
getFormFormat(country) {
|
||||||
|
return {
|
||||||
|
"addressLevel1Label": country == "US" ? "state" : "province",
|
||||||
|
"postalCodeLabel": country == "US" ? "zip" : "postalCode",
|
||||||
|
"fieldsOrder": [
|
||||||
|
{fieldId: "name", newLine: true},
|
||||||
|
{fieldId: "organization", newLine: true},
|
||||||
|
{fieldId: "street-address", newLine: true},
|
||||||
|
{fieldId: "address-level2"},
|
||||||
|
{fieldId: "address-level1"},
|
||||||
|
{fieldId: "postal-code"},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,6 +6,7 @@ skip-if = !e10s # Bug 1365964 - Payment Request isn't implemented for non-e10s
|
||||||
support-files =
|
support-files =
|
||||||
blank_page.html
|
blank_page.html
|
||||||
|
|
||||||
|
[browser_address_edit.js]
|
||||||
[browser_card_edit.js]
|
[browser_card_edit.js]
|
||||||
[browser_change_shipping.js]
|
[browser_change_shipping.js]
|
||||||
[browser_host_name.js]
|
[browser_host_name.js]
|
||||||
|
|
|
@ -0,0 +1,157 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
add_task(async function test_add_link() {
|
||||||
|
await BrowserTestUtils.withNewTab({
|
||||||
|
gBrowser,
|
||||||
|
url: BLANK_PAGE_URL,
|
||||||
|
}, async browser => {
|
||||||
|
let {win, frame} =
|
||||||
|
await setupPaymentDialog(browser, {
|
||||||
|
methodData: [PTU.MethodData.basicCard],
|
||||||
|
details: PTU.Details.twoShippingOptions,
|
||||||
|
options: PTU.Options.requestShippingOption,
|
||||||
|
merchantTaskFn: PTU.ContentTasks.createAndShowRequest,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
let shippingAddressChangePromise = ContentTask.spawn(browser, {
|
||||||
|
eventName: "shippingaddresschange",
|
||||||
|
}, PTU.ContentTasks.awaitPaymentRequestEventPromise);
|
||||||
|
|
||||||
|
const EXPECTED_ADDRESS = {
|
||||||
|
"given-name": "Jared",
|
||||||
|
"family-name": "Wein",
|
||||||
|
"organization": "Mozilla",
|
||||||
|
"street-address": "404 Internet Lane",
|
||||||
|
"address-level2": "Firefoxity City",
|
||||||
|
"address-level1": "CA",
|
||||||
|
"postal-code": "31337",
|
||||||
|
"country": "US",
|
||||||
|
"tel": "+15555551212",
|
||||||
|
"email": "test@example.com",
|
||||||
|
};
|
||||||
|
|
||||||
|
await spawnPaymentDialogTask(frame, async (address) => {
|
||||||
|
let {
|
||||||
|
PaymentTestUtils: PTU,
|
||||||
|
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
|
||||||
|
|
||||||
|
let addLink = content.document.querySelector("address-picker a");
|
||||||
|
is(addLink.textContent, "Add", "Add link text");
|
||||||
|
|
||||||
|
addLink.click();
|
||||||
|
|
||||||
|
let state = await PTU.DialogContentUtils.waitForState(content, (state) => {
|
||||||
|
return state.page.id == "address-page" && !state.page.guid;
|
||||||
|
}, "Check add page state");
|
||||||
|
|
||||||
|
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;
|
||||||
|
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");
|
||||||
|
|
||||||
|
let addressGUIDs = Object.keys(state.savedAddresses);
|
||||||
|
is(addressGUIDs.length, 1, "Check there is one address");
|
||||||
|
let savedAddress = state.savedAddresses[addressGUIDs[0]];
|
||||||
|
for (let [key, val] of Object.entries(address)) {
|
||||||
|
is(savedAddress[key], val, "Check " + key);
|
||||||
|
}
|
||||||
|
|
||||||
|
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
|
||||||
|
return state.page.id == "payment-summary";
|
||||||
|
}, "Switched back to payment-summary");
|
||||||
|
}, EXPECTED_ADDRESS);
|
||||||
|
|
||||||
|
await shippingAddressChangePromise;
|
||||||
|
info("got shippingaddresschange event");
|
||||||
|
|
||||||
|
info("clicking cancel");
|
||||||
|
await spawnPaymentDialogTask(frame, PTU.DialogContentTasks.manuallyClickCancel);
|
||||||
|
|
||||||
|
await BrowserTestUtils.waitForCondition(() => win.closed, "dialog should be closed");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_edit_link() {
|
||||||
|
await BrowserTestUtils.withNewTab({
|
||||||
|
gBrowser,
|
||||||
|
url: BLANK_PAGE_URL,
|
||||||
|
}, async browser => {
|
||||||
|
let {win, frame} =
|
||||||
|
await setupPaymentDialog(browser, {
|
||||||
|
methodData: [PTU.MethodData.basicCard],
|
||||||
|
details: PTU.Details.twoShippingOptions,
|
||||||
|
options: PTU.Options.requestShippingOption,
|
||||||
|
merchantTaskFn: PTU.ContentTasks.createAndShowRequest,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
let shippingAddressChangePromise = ContentTask.spawn(browser, {
|
||||||
|
eventName: "shippingaddresschange",
|
||||||
|
}, PTU.ContentTasks.awaitPaymentRequestEventPromise);
|
||||||
|
|
||||||
|
const EXPECTED_ADDRESS = {
|
||||||
|
"given-name": "Jaws",
|
||||||
|
"family-name": "swaJ",
|
||||||
|
"organization": "aliizoM",
|
||||||
|
};
|
||||||
|
|
||||||
|
await spawnPaymentDialogTask(frame, async (address) => {
|
||||||
|
let {
|
||||||
|
PaymentTestUtils: PTU,
|
||||||
|
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
|
||||||
|
|
||||||
|
let editLink = content.document.querySelector("address-picker a:nth-of-type(2)");
|
||||||
|
is(editLink.textContent, "Edit", "Edit link text");
|
||||||
|
|
||||||
|
editLink.click();
|
||||||
|
|
||||||
|
let state = await PTU.DialogContentUtils.waitForState(content, (state) => {
|
||||||
|
return state.page.id == "address-page" && !!state.page.guid;
|
||||||
|
}, "Check edit page state");
|
||||||
|
|
||||||
|
info("overwriting field values");
|
||||||
|
for (let [key, val] of Object.entries(address)) {
|
||||||
|
let field = content.document.getElementById(key);
|
||||||
|
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 Object.keys(state.savedAddresses).length == 1;
|
||||||
|
}, "Check address was edited");
|
||||||
|
|
||||||
|
let addressGUIDs = Object.keys(state.savedAddresses);
|
||||||
|
is(addressGUIDs.length, 1, "Check there is still one address");
|
||||||
|
let savedAddress = state.savedAddresses[addressGUIDs[0]];
|
||||||
|
for (let [key, val] of Object.entries(address)) {
|
||||||
|
is(savedAddress[key], val, "Check updated " + key);
|
||||||
|
}
|
||||||
|
|
||||||
|
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
|
||||||
|
return state.page.id == "payment-summary";
|
||||||
|
}, "Switched back to payment-summary");
|
||||||
|
}, EXPECTED_ADDRESS);
|
||||||
|
|
||||||
|
await shippingAddressChangePromise;
|
||||||
|
info("got shippingaddresschange event");
|
||||||
|
|
||||||
|
info("clicking cancel");
|
||||||
|
await spawnPaymentDialogTask(frame, PTU.DialogContentTasks.manuallyClickCancel);
|
||||||
|
|
||||||
|
await BrowserTestUtils.waitForCondition(() => win.closed, "dialog should be closed");
|
||||||
|
});
|
||||||
|
await cleanupFormAutofillStorage();
|
||||||
|
});
|
|
@ -17,8 +17,7 @@ add_task(async function test_add_link() {
|
||||||
|
|
||||||
let state = await PTU.DialogContentUtils.waitForState(content, (state) => {
|
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.page.guid;
|
||||||
},
|
}, "Check add page state");
|
||||||
"Check add page state");
|
|
||||||
|
|
||||||
ok(!state.isPrivate,
|
ok(!state.isPrivate,
|
||||||
"isPrivate flag is not set when paymentrequest is shown from a non-private session");
|
"isPrivate flag is not set when paymentrequest is shown from a non-private session");
|
||||||
|
@ -44,8 +43,7 @@ add_task(async function test_add_link() {
|
||||||
|
|
||||||
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
|
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
|
||||||
return Object.keys(state.savedBasicCards).length == 1;
|
return Object.keys(state.savedBasicCards).length == 1;
|
||||||
},
|
}, "Check card was added");
|
||||||
"Check card was added");
|
|
||||||
|
|
||||||
let cardGUIDs = Object.keys(state.savedBasicCards);
|
let cardGUIDs = Object.keys(state.savedBasicCards);
|
||||||
is(cardGUIDs.length, 1, "Check there is one card");
|
is(cardGUIDs.length, 1, "Check there is one card");
|
||||||
|
@ -57,8 +55,7 @@ add_task(async function test_add_link() {
|
||||||
|
|
||||||
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
|
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
|
||||||
return state.page.id == "payment-summary";
|
return state.page.id == "payment-summary";
|
||||||
},
|
}, "Switched back to payment-summary");
|
||||||
"Switched back to payment-summary");
|
|
||||||
}, args);
|
}, args);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -79,8 +76,7 @@ add_task(async function test_edit_link() {
|
||||||
|
|
||||||
let state = await PTU.DialogContentUtils.waitForState(content, (state) => {
|
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.page.guid;
|
||||||
},
|
}, "Check edit page state");
|
||||||
"Check edit page state");
|
|
||||||
|
|
||||||
let nextYear = (new Date()).getFullYear() + 1;
|
let nextYear = (new Date()).getFullYear() + 1;
|
||||||
let card = {
|
let card = {
|
||||||
|
@ -102,8 +98,7 @@ add_task(async function test_edit_link() {
|
||||||
|
|
||||||
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
|
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
|
||||||
return Object.keys(state.savedBasicCards).length == 1;
|
return Object.keys(state.savedBasicCards).length == 1;
|
||||||
},
|
}, "Check card was added");
|
||||||
"Check card was added");
|
|
||||||
|
|
||||||
let cardGUIDs = Object.keys(state.savedBasicCards);
|
let cardGUIDs = Object.keys(state.savedBasicCards);
|
||||||
is(cardGUIDs.length, 1, "Check there is still one card");
|
is(cardGUIDs.length, 1, "Check there is still one card");
|
||||||
|
@ -115,8 +110,7 @@ add_task(async function test_edit_link() {
|
||||||
|
|
||||||
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
|
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
|
||||||
return state.page.id == "payment-summary";
|
return state.page.id == "payment-summary";
|
||||||
},
|
}, "Switched back to payment-summary");
|
||||||
"Switched back to payment-summary");
|
|
||||||
}, args);
|
}, args);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -4,5 +4,6 @@
|
||||||
# to resemble the layout in the shipped JAR file.
|
# to resemble the layout in the shipped JAR file.
|
||||||
support-files =
|
support-files =
|
||||||
../../../../../../browser/extensions/formautofill/content/editCreditCard.xhtml
|
../../../../../../browser/extensions/formautofill/content/editCreditCard.xhtml
|
||||||
|
../../../../../../browser/extensions/formautofill/content/editAddress.xhtml
|
||||||
|
|
||||||
[test_editCreditCard.html]
|
[test_editCreditCard.html]
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
prefs =
|
prefs =
|
||||||
dom.webcomponents.customelements.enabled=false
|
dom.webcomponents.customelements.enabled=false
|
||||||
support-files =
|
support-files =
|
||||||
|
!/browser/extensions/formautofill/content/editAddress.xhtml
|
||||||
!/browser/extensions/formautofill/content/editCreditCard.xhtml
|
!/browser/extensions/formautofill/content/editCreditCard.xhtml
|
||||||
../../../../../browser/extensions/formautofill/content/autofillEditForms.js
|
../../../../../browser/extensions/formautofill/content/autofillEditForms.js
|
||||||
../../../../../testing/modules/sinon-2.3.2.js
|
../../../../../testing/modules/sinon-2.3.2.js
|
||||||
|
@ -9,6 +10,7 @@ support-files =
|
||||||
payments_common.js
|
payments_common.js
|
||||||
skip-if = !e10s
|
skip-if = !e10s
|
||||||
|
|
||||||
|
[test_address_form.html]
|
||||||
[test_address_picker.html]
|
[test_address_picker.html]
|
||||||
[test_basic_card_form.html]
|
[test_basic_card_form.html]
|
||||||
[test_currency_amount.html]
|
[test_currency_amount.html]
|
||||||
|
|
|
@ -0,0 +1,231 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
Test the address-form element
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Test the address-form element</title>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/AddTask.js"></script>
|
||||||
|
<script src="sinon-2.3.2.js"></script>
|
||||||
|
<script src="payments_common.js"></script>
|
||||||
|
<script src="../../res/vendor/custom-elements.min.js"></script>
|
||||||
|
<script src="../../res/unprivileged-fallbacks.js"></script>
|
||||||
|
<script src="autofillEditForms.js"></script>
|
||||||
|
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
<link rel="stylesheet" type="text/css" href="../../res/paymentRequest.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p id="display">
|
||||||
|
</p>
|
||||||
|
<div id="content" style="display: none">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<pre id="test">
|
||||||
|
</pre>
|
||||||
|
<script type="module">
|
||||||
|
/** Test the address-form element **/
|
||||||
|
|
||||||
|
/* global sinon */
|
||||||
|
/* import-globals-from payments_common.js */
|
||||||
|
|
||||||
|
import AddressForm from "../../res/containers/address-form.js";
|
||||||
|
|
||||||
|
let display = document.getElementById("display");
|
||||||
|
|
||||||
|
function checkAddressForm(customEl, expectedAddress) {
|
||||||
|
const ADDRESS_PROPERTY_NAMES = [
|
||||||
|
"given-name",
|
||||||
|
"family-name",
|
||||||
|
"organization",
|
||||||
|
"street-address",
|
||||||
|
"address-level2",
|
||||||
|
"address-level1",
|
||||||
|
"postal-code",
|
||||||
|
"country",
|
||||||
|
"email",
|
||||||
|
"tel",
|
||||||
|
];
|
||||||
|
for (let propName of ADDRESS_PROPERTY_NAMES) {
|
||||||
|
let expectedVal = expectedAddress[propName] || "";
|
||||||
|
is(document.getElementById(propName).value,
|
||||||
|
expectedVal.toString(),
|
||||||
|
`Check ${propName}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
add_task(async function test_initialState() {
|
||||||
|
let form = new AddressForm();
|
||||||
|
let {page} = form.requestStore.getState();
|
||||||
|
is(page.id, "payment-summary", "Check initial page");
|
||||||
|
await form.promiseReady;
|
||||||
|
display.appendChild(form);
|
||||||
|
await asyncElementRendered();
|
||||||
|
is(page.id, "payment-summary", "Check initial page after appending");
|
||||||
|
form.remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_backButton() {
|
||||||
|
let form = new AddressForm();
|
||||||
|
form.dataset.backButtonLabel = "Back";
|
||||||
|
await form.requestStore.setState({
|
||||||
|
page: {
|
||||||
|
id: "test-page",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await form.promiseReady;
|
||||||
|
display.appendChild(form);
|
||||||
|
await asyncElementRendered();
|
||||||
|
|
||||||
|
let stateChangePromise = promiseStateChange(form.requestStore);
|
||||||
|
is(form.backButton.textContent, "Back", "Check label");
|
||||||
|
form.backButton.scrollIntoView();
|
||||||
|
synthesizeMouseAtCenter(form.backButton, {});
|
||||||
|
|
||||||
|
let {page} = await stateChangePromise;
|
||||||
|
is(page.id, "payment-summary", "Check initial page after appending");
|
||||||
|
|
||||||
|
form.remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_saveButton() {
|
||||||
|
let form = new AddressForm();
|
||||||
|
form.dataset.saveButtonLabel = "Save";
|
||||||
|
form.dataset.errorGenericSave = "Generic error";
|
||||||
|
await form.promiseReady;
|
||||||
|
display.appendChild(form);
|
||||||
|
await asyncElementRendered();
|
||||||
|
|
||||||
|
form.form.querySelector("#given-name").focus();
|
||||||
|
sendString("Jaws");
|
||||||
|
form.form.querySelector("#family-name").focus();
|
||||||
|
sendString("Swaj");
|
||||||
|
form.form.querySelector("#organization").focus();
|
||||||
|
sendString("Allizom");
|
||||||
|
form.form.querySelector("#street-address").focus();
|
||||||
|
sendString("404 Internet Super Highway");
|
||||||
|
form.form.querySelector("#address-level2").focus();
|
||||||
|
sendString("Firefoxity City");
|
||||||
|
form.form.querySelector("#address-level1").focus();
|
||||||
|
sendString("CA");
|
||||||
|
form.form.querySelector("#postal-code").focus();
|
||||||
|
sendString("00001");
|
||||||
|
form.form.querySelector("#country option[value='US']").selected = true;
|
||||||
|
form.form.querySelector("#email").focus();
|
||||||
|
sendString("test@example.com");
|
||||||
|
form.form.querySelector("#tel").focus();
|
||||||
|
sendString("+15555551212");
|
||||||
|
|
||||||
|
let messagePromise = promiseContentToChromeMessage("updateAutofillRecord");
|
||||||
|
is(form.saveButton.textContent, "Save", "Check label");
|
||||||
|
form.saveButton.scrollIntoView();
|
||||||
|
synthesizeMouseAtCenter(form.saveButton, {});
|
||||||
|
|
||||||
|
let details = await messagePromise;
|
||||||
|
is(details.collectionName, "addresses", "Check collectionName");
|
||||||
|
isDeeply(details, {
|
||||||
|
collectionName: "addresses",
|
||||||
|
errorStateChange: {
|
||||||
|
page: {
|
||||||
|
id: "address-page",
|
||||||
|
error: "Generic error",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
guid: undefined,
|
||||||
|
messageType: "updateAutofillRecord",
|
||||||
|
preserveOldProperties: true,
|
||||||
|
record: {
|
||||||
|
"given-name": "Jaws",
|
||||||
|
"family-name": "Swaj",
|
||||||
|
"organization": "Allizom",
|
||||||
|
"street-address": "404 Internet Super Highway",
|
||||||
|
"address-level2": "Firefoxity City",
|
||||||
|
"address-level1": "CA",
|
||||||
|
"postal-code": "00001",
|
||||||
|
"country": "US",
|
||||||
|
"email": "test@example.com",
|
||||||
|
"tel": "+15555551212",
|
||||||
|
},
|
||||||
|
selectedStateKey: undefined,
|
||||||
|
successStateChange: {
|
||||||
|
page: {
|
||||||
|
id: "payment-summary",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, "Check event details for the message to chrome");
|
||||||
|
form.remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_genericError() {
|
||||||
|
let form = new AddressForm();
|
||||||
|
await form.requestStore.setState({
|
||||||
|
page: {
|
||||||
|
id: "test-page",
|
||||||
|
error: "Generic Error",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await form.promiseReady;
|
||||||
|
display.appendChild(form);
|
||||||
|
await asyncElementRendered();
|
||||||
|
|
||||||
|
ok(!isHidden(form.genericErrorText), "Error message should be visible");
|
||||||
|
is(form.genericErrorText.textContent, "Generic Error", "Check error message");
|
||||||
|
form.remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_edit() {
|
||||||
|
let form = new AddressForm();
|
||||||
|
await form.promiseReady;
|
||||||
|
display.appendChild(form);
|
||||||
|
await asyncElementRendered();
|
||||||
|
|
||||||
|
let address1 = deepClone(PTU.Addresses.TimBL);
|
||||||
|
address1.guid = "9864798564";
|
||||||
|
|
||||||
|
await form.requestStore.setState({
|
||||||
|
page: {
|
||||||
|
id: "address-page",
|
||||||
|
guid: address1.guid,
|
||||||
|
},
|
||||||
|
savedAddresses: {
|
||||||
|
[address1.guid]: deepClone(address1),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await asyncElementRendered();
|
||||||
|
checkAddressForm(form, address1);
|
||||||
|
|
||||||
|
info("test change to minimal record");
|
||||||
|
let minimalAddress = {
|
||||||
|
"given-name": address1["given-name"],
|
||||||
|
guid: "9gnjdhen46",
|
||||||
|
};
|
||||||
|
await form.requestStore.setState({
|
||||||
|
page: {
|
||||||
|
id: "address-page",
|
||||||
|
guid: minimalAddress.guid,
|
||||||
|
},
|
||||||
|
savedAddresses: {
|
||||||
|
[minimalAddress.guid]: deepClone(minimalAddress),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await asyncElementRendered();
|
||||||
|
checkAddressForm(form, minimalAddress);
|
||||||
|
|
||||||
|
info("change to no selected address");
|
||||||
|
await form.requestStore.setState({
|
||||||
|
page: {
|
||||||
|
id: "address-page",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await asyncElementRendered();
|
||||||
|
checkAddressForm(form, {});
|
||||||
|
|
||||||
|
form.remove();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
Загрузка…
Ссылка в новой задаче