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:
Jared Wein 2018-04-10 11:53:16 -04:00
Родитель 2d7d260a1e
Коммит 9963ec2b5f
14 изменённых файлов: 640 добавлений и 15 удалений

Просмотреть файл

@ -144,6 +144,8 @@ update.locale
browser/chrome/browser/content/branding/icon128.png
browser/chrome/devtools/content/framework/dev-edition-promo/dev-edition-logo.png
# 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
chrome/toolkit/res/payments/formautofill/editCreditCard.xhtml
browser/features/formautofill@mozilla.org/chrome/content/autofillEditForms.js

Просмотреть файл

@ -65,7 +65,11 @@ let PaymentFrameScript = {
* Expose privileged utility functions to the unprivileged page.
*/
exposeUtilityFunctions() {
let waivedContent = Cu.waiveXrays(content);
let PaymentDialogUtils = {
DEFAULT_REGION: FormAutofillUtils.DEFAULT_REGION,
supportedCountries: FormAutofillUtils.supportedCountries,
getAddressLabel(address) {
return FormAutofillUtils.getAddressLabel(address);
},
@ -73,8 +77,12 @@ let PaymentFrameScript = {
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, {
cloneFunctions: true,
});

Просмотреть файл

@ -19,6 +19,7 @@ toolkit.jar:
res/payments/debugging.html (res/debugging.html)
res/payments/debugging.js (res/debugging.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/unprivileged-fallbacks.js (res/unprivileged-fallbacks.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>
* Container around <rich-select> (eventually providing add/edit links) with
* Container around add/edit links and <rich-select> with
* <address-option> listening to savedAddresses.
*/
@ -21,10 +21,21 @@ export default class AddressPicker extends PaymentStateSubscriberMixin(HTMLEleme
super();
this.dropdown = new RichSelect();
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() {
this.appendChild(this.dropdown);
this.appendChild(this.addLink);
this.append(" ");
this.appendChild(this.editLink);
super.connectedCallback();
}
@ -134,6 +145,9 @@ export default class AddressPicker extends PaymentStateSubscriberMixin(HTMLEleme
this.onChange(event);
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);

Просмотреть файл

@ -9,6 +9,7 @@ import paymentRequest from "../paymentRequest.js";
import "../components/currency-amount.js";
import "./address-picker.js";
import "./address-form.js";
import "./basic-card-form.js";
import "./order-details.js";
import "./payment-method-picker.js";

Просмотреть файл

@ -13,8 +13,12 @@
<!ENTITY pickupAddressLabel "Pickup Address">
<!ENTITY shippingOptionsLabel "Shipping Options">
<!ENTITY paymentMethodsLabel "Payment Method">
<!ENTITY address.addLink.label "Add">
<!ENTITY address.editLink.label "Edit">
<!ENTITY basicCard.addLink.label "Add">
<!ENTITY basicCard.editLink.label "Edit">
<!ENTITY payer.addLink.label "Add">
<!ENTITY payer.editLink.label "Edit">
<!ENTITY payerLabel "Contact Information">
<!ENTITY cancelPaymentButton.label "Cancel">
<!ENTITY approvePaymentButton.label "Pay">
@ -28,6 +32,9 @@
<!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)">
<!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">
<head>
@ -75,7 +82,10 @@
data-shipping-address-label="&shippingAddressLabel;"
data-delivery-address-label="&deliveryAddressLabel;"
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>
<shipping-option-picker class="shipping-related"></shipping-option-picker>
@ -88,6 +98,8 @@
<div class="payer-related"><label>&payerLabel;</label></div>
<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>
<div id="error-text"></div>
</section>
@ -114,6 +126,13 @@
data-save-button-label="&basicCardPage.saveButton.label;"
data-persist-checkbox-label="&basicCardPage.persistCheckbox.label;"
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 id="disabled-overlay" hidden="hidden">

Просмотреть файл

@ -28,4 +28,20 @@ var PaymentDialogUtils = {
isCCNumber(str) {
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 =
blank_page.html
[browser_address_edit.js]
[browser_card_edit.js]
[browser_change_shipping.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) => {
return state.page.id == "basic-card-page" && !state.page.guid;
},
"Check add page state");
}, "Check add page state");
ok(!state.isPrivate,
"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) => {
return Object.keys(state.savedBasicCards).length == 1;
},
"Check card was added");
}, "Check card was added");
let cardGUIDs = Object.keys(state.savedBasicCards);
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) => {
return state.page.id == "payment-summary";
},
"Switched back to payment-summary");
}, "Switched back to payment-summary");
}, args);
});
@ -79,8 +76,7 @@ add_task(async function test_edit_link() {
let state = await PTU.DialogContentUtils.waitForState(content, (state) => {
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 card = {
@ -102,8 +98,7 @@ add_task(async function test_edit_link() {
state = await PTU.DialogContentUtils.waitForState(content, (state) => {
return Object.keys(state.savedBasicCards).length == 1;
},
"Check card was added");
}, "Check card was added");
let cardGUIDs = Object.keys(state.savedBasicCards);
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) => {
return state.page.id == "payment-summary";
},
"Switched back to payment-summary");
}, "Switched back to payment-summary");
}, args);
});

Просмотреть файл

@ -4,5 +4,6 @@
# to resemble the layout in the shipped JAR file.
support-files =
../../../../../../browser/extensions/formautofill/content/editCreditCard.xhtml
../../../../../../browser/extensions/formautofill/content/editAddress.xhtml
[test_editCreditCard.html]

Просмотреть файл

@ -2,6 +2,7 @@
prefs =
dom.webcomponents.customelements.enabled=false
support-files =
!/browser/extensions/formautofill/content/editAddress.xhtml
!/browser/extensions/formautofill/content/editCreditCard.xhtml
../../../../../browser/extensions/formautofill/content/autofillEditForms.js
../../../../../testing/modules/sinon-2.3.2.js
@ -9,6 +10,7 @@ support-files =
payments_common.js
skip-if = !e10s
[test_address_form.html]
[test_address_picker.html]
[test_basic_card_form.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>