fune/browser/components/payments/test/mochitest/test_address_form.html

956 lines
32 KiB
HTML

<!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/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"/>
<link rel="stylesheet" type="text/css" href="editDialog-shared.css"/>
<link rel="stylesheet" type="text/css" href="../../res/containers/address-form.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, PaymentDialogUtils */
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}`);
}
}
function sendStringAndCheckValidity(element, string, isValid) {
fillField(element, string);
ok(element.checkValidity() == isValid,
`${element.id} should be ${isValid ? "valid" : "invalid"} ("${string}")`);
}
add_task(async function test_initialState() {
let form = new AddressForm();
form.id = "shipping-address-page";
form.setAttribute("selected-state-key", "selectedShippingAddress");
await form.requestStore.setState({
"test-page": {},
});
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");
// :-moz-ui-invalid, unlike :invalid, only applies to fields showing the error outline.
let fieldsVisiblyInvalid = form.querySelectorAll(":-moz-ui-invalid");
is(fieldsVisiblyInvalid.length, 0, "Check no fields are visibly invalid on an empty 'add' form");
form.remove();
});
add_task(async function test_pageTitle() {
let address1 = deepClone(PTU.Addresses.TimBL);
address1.guid = "9864798564";
// the element can have all the data attributes. We'll add them all up front
let form = new AddressForm();
let id = "shipping-address-page";
form.id = id;
form.dataset.titleAdd = `Add Title`;
form.dataset.titleEdit = `Edit Title`;
form.setAttribute("selected-state-key", "selectedShippingAddress");
await form.promiseReady;
display.appendChild(form);
let newState = {
page: { id },
[id]: {},
savedAddresses: {
[address1.guid]: address1,
},
request: {
paymentDetails: {},
paymentOptions: { shippingOption: "shipping" },
},
};
await form.requestStore.setState(newState);
await asyncElementRendered();
is(form.pageTitleHeading.textContent, "Add Title", "Check 'add' title");
// test the 'edit' variation
newState = deepClone(newState);
newState[id].guid = address1.guid;
await form.requestStore.setState(newState);
await asyncElementRendered();
is(form.pageTitleHeading.textContent, "Edit Title", "Check 'edit' title");
form.remove();
});
add_task(async function test_backButton() {
let form = new AddressForm();
form.id = "test-page";
form.dataset.titleAdd = "Sample add page title";
form.dataset.backButtonLabel = "Back";
form.setAttribute("selected-state-key", "selectedShippingAddress");
await form.promiseReady;
display.appendChild(form);
await form.requestStore.setState({
"test-page": {},
page: {
id: "test-page",
},
request: {
paymentDetails: {},
paymentOptions: {},
},
});
await asyncElementRendered();
let stateChangePromise = promiseStateChange(form.requestStore);
is(form.pageTitleHeading.textContent, "Sample add page title", "Check title");
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.id = "shipping-address-page";
form.setAttribute("selected-state-key", "selectedShippingAddress");
form.dataset.nextButtonLabel = "Next";
form.dataset.errorGenericSave = "Generic error";
await form.promiseReady;
display.appendChild(form);
form.requestStore.setState({
page: {
id: "shipping-address-page",
},
"shipping-address-page": {},
});
await asyncElementRendered();
ok(form.saveButton.disabled, "Save button initially disabled");
fillField(form.form.querySelector("#given-name"), "Jaws");
fillField(form.form.querySelector("#family-name"), "Swaj");
fillField(form.form.querySelector("#organization"), "Allizom");
fillField(form.form.querySelector("#street-address"), "404 Internet Super Highway");
fillField(form.form.querySelector("#address-level2"), "Firefoxity City");
fillField(form.form.querySelector("#country"), "US");
fillField(form.form.querySelector("#address-level1"), "CA");
fillField(form.form.querySelector("#postal-code"), "00001");
fillField(form.form.querySelector("#tel"), "+15555551212");
ok(!form.saveButton.disabled, "Save button is enabled after filling");
info("blanking the street-address");
fillField(form.form.querySelector("#street-address"), "");
ok(form.saveButton.disabled, "Save button is disabled after blanking street-address");
form.form.querySelector("#street-address").blur();
let fieldsVisiblyInvalid = form.querySelectorAll(":-moz-ui-invalid");
is(fieldsVisiblyInvalid.length, 1, "Check 1 field visibly invalid after blanking and blur");
is(fieldsVisiblyInvalid[0].id, "street-address", "Check #street-address is visibly invalid");
fillField(form.form.querySelector("#street-address"), "404 Internet Super Highway");
is(form.querySelectorAll(":-moz-ui-invalid").length, 0, "Check no fields visibly invalid");
ok(!form.saveButton.disabled, "Save button is enabled after re-filling street-address");
fillField(form.form.querySelector("#country"), "CA");
ok(form.saveButton.disabled, "Save button is disabled after changing the country to Canada");
fillField(form.form.querySelector("#country"), "US");
ok(form.saveButton.disabled,
"Save button is disabled after changing the country back to US since address-level1 " +
"got cleared when changing countries");
fillField(form.form.querySelector("#address-level1"), "CA");
ok(!form.saveButton.disabled, "Save button is enabled after re-entering address-level1");
let messagePromise = promiseContentToChromeMessage("updateAutofillRecord");
is(form.saveButton.textContent, "Next", "Check label");
form.saveButton.scrollIntoView();
synthesizeMouseAtCenter(form.saveButton, {});
let details = await messagePromise;
ok(typeof(details.messageID) == "number" && details.messageID > 0, "Check messageID type");
delete details.messageID;
is(details.collectionName, "addresses", "Check collectionName");
isDeeply(details, {
collectionName: "addresses",
guid: undefined,
messageType: "updateAutofillRecord",
record: {
"given-name": "Jaws",
"family-name": "Swaj",
"additional-name": "",
"organization": "Allizom",
"street-address": "404 Internet Super Highway",
"address-level3": "",
"address-level2": "Firefoxity City",
"address-level1": "CA",
"postal-code": "00001",
"country": "US",
"tel": "+15555551212",
},
}, "Check event details for the message to chrome");
form.remove();
});
add_task(async function test_genericError() {
let form = new AddressForm();
form.id = "test-page";
form.setAttribute("selected-state-key", "selectedShippingAddress");
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();
form.id = "shipping-address-page";
form.dataset.updateButtonLabel = "Update";
form.setAttribute("selected-state-key", "selectedShippingAddress");
await form.promiseReady;
display.appendChild(form);
await asyncElementRendered();
let address1 = deepClone(PTU.Addresses.TimBL);
address1.guid = "9864798564";
await form.requestStore.setState({
page: {
id: "shipping-address-page",
},
"shipping-address-page": {
guid: address1.guid,
},
savedAddresses: {
[address1.guid]: deepClone(address1),
},
});
await asyncElementRendered();
is(form.querySelectorAll(":-moz-ui-invalid").length, 0,
"Check no fields are visibly invalid on an 'edit' form with a complete address");
checkAddressForm(form, address1);
ok(!form.saveButton.disabled, "Save button should be enabled upon edit for a valid address");
info("test change to minimal record");
let minimalAddress = {
"given-name": address1["given-name"],
guid: "9gnjdhen46",
};
await form.requestStore.setState({
page: {
id: "shipping-address-page",
},
"shipping-address-page": {
guid: minimalAddress.guid,
},
savedAddresses: {
[minimalAddress.guid]: deepClone(minimalAddress),
},
});
await asyncElementRendered();
is(form.saveButton.textContent, "Update", "Check label");
checkAddressForm(form, minimalAddress);
ok(form.saveButton.disabled, "Save button should be disabled if only the name is filled");
ok(form.querySelectorAll(":-moz-ui-invalid").length > 3,
"Check fields are visibly invalid on an 'edit' form with only the given-name filled");
is(form.querySelectorAll("#country:-moz-ui-invalid").length, 1,
"Check that the country `select` is marked as invalid");
info("change to no selected address");
await form.requestStore.setState({
page: {
id: "shipping-address-page",
},
"shipping-address-page": {},
});
await asyncElementRendered();
is(form.querySelectorAll(":-moz-ui-invalid").length, 0,
"Check no fields are visibly invalid on an empty 'add' form after being an edit form");
checkAddressForm(form, {
country: "US",
});
ok(form.saveButton.disabled, "Save button should be disabled for an empty form");
form.remove();
});
add_task(async function test_restricted_address_fields() {
let form = new AddressForm();
form.id = "payer-address-page";
form.setAttribute("selected-state-key", "selectedPayerAddress");
form.dataset.errorGenericSave = "Generic error";
form.dataset.fieldRequiredSymbol = "*";
form.dataset.nextButtonLabel = "Next";
await form.promiseReady;
form.form.dataset.extraRequiredFields = "name email tel";
display.appendChild(form);
await form.requestStore.setState({
page: {
id: "payer-address-page",
},
"payer-address-page": {
addressFields: "name email tel",
},
});
await asyncElementRendered();
ok(form.saveButton.disabled, "Save button should be disabled due to empty fields");
ok(!isHidden(form.form.querySelector("#given-name")),
"given-name should be visible");
ok(!isHidden(form.form.querySelector("#additional-name")),
"additional-name should be visible");
ok(!isHidden(form.form.querySelector("#family-name")),
"family-name should be visible");
ok(isHidden(form.form.querySelector("#organization")),
"organization should be hidden");
ok(isHidden(form.form.querySelector("#street-address")),
"street-address should be hidden");
ok(isHidden(form.form.querySelector("#address-level2")),
"address-level2 should be hidden");
ok(isHidden(form.form.querySelector("#address-level1")),
"address-level1 should be hidden");
ok(isHidden(form.form.querySelector("#postal-code")),
"postal-code should be hidden");
ok(isHidden(form.form.querySelector("#country")),
"country should be hidden");
ok(!isHidden(form.form.querySelector("#email")),
"email should be visible");
let telField = form.form.querySelector("#tel");
ok(!isHidden(telField),
"tel should be visible");
let telContainer = telField.closest(`#${telField.id}-container`);
ok(telContainer.hasAttribute("required"), "tel container should have required attribute");
let telSpan = telContainer.querySelector("span");
is(telSpan.getAttribute("fieldRequiredSymbol"), "*",
"tel span should have asterisk as fieldRequiredSymbol");
is(getComputedStyle(telSpan, "::after").content, "attr(fieldRequiredSymbol)",
"Asterisk should be on tel");
fillField(form.form.querySelector("#given-name"), "John");
fillField(form.form.querySelector("#family-name"), "Smith");
ok(form.saveButton.disabled, "Save button should be disabled due to empty fields");
fillField(form.form.querySelector("#email"), "john@example.com");
ok(form.saveButton.disabled,
"Save button should be disabled due to empty fields");
fillField(form.form.querySelector("#tel"), "+15555555555");
ok(!form.saveButton.disabled, "Save button should be enabled with all required fields filled");
form.remove();
await form.requestStore.setState({
"payer-address-page": {},
});
});
add_task(async function test_field_validation() {
let form = new AddressForm();
form.id = "shipping-address-page";
form.setAttribute("selected-state-key", "selectedShippingAddress");
form.dataset.fieldRequiredSymbol = "*";
await form.promiseReady;
display.appendChild(form);
await form.requestStore.setState({
page: {
id: "shipping-address-page",
},
});
await asyncElementRendered();
let postalCodeInput = form.form.querySelector("#postal-code");
let addressLevel1Input = form.form.querySelector("#address-level1");
ok(!postalCodeInput.value, "postal-code should be empty by default");
ok(!addressLevel1Input.value, "address-level1 should be empty by default");
ok(!postalCodeInput.checkValidity(), "postal-code should be invalid by default");
ok(!addressLevel1Input.checkValidity(), "address-level1 should be invalid by default");
let countrySelect = form.form.querySelector("#country");
let requiredFields = [
form.form.querySelector("#given-name"),
form.form.querySelector("#street-address"),
form.form.querySelector("#address-level2"),
postalCodeInput,
addressLevel1Input,
countrySelect,
];
for (let field of requiredFields) {
let container = field.closest(`#${field.id}-container`);
ok(container.hasAttribute("required"), `#${field.id} container should have required attribute`);
let span = container.querySelector("span");
is(span.getAttribute("fieldRequiredSymbol"), "*",
"span should have asterisk as fieldRequiredSymbol");
is(getComputedStyle(span, "::after").content, "attr(fieldRequiredSymbol)",
"Asterisk should be on " + field.id);
}
ok(form.saveButton.disabled, "Save button should be disabled upon load");
fillField(countrySelect, "US");
sendStringAndCheckValidity(addressLevel1Input, "MI", true);
sendStringAndCheckValidity(addressLevel1Input, "", false);
sendStringAndCheckValidity(postalCodeInput, "B4N4N4", false);
sendStringAndCheckValidity(addressLevel1Input, "NS", false);
sendStringAndCheckValidity(postalCodeInput, "R3J 3C7", false);
sendStringAndCheckValidity(addressLevel1Input, "", false);
sendStringAndCheckValidity(postalCodeInput, "11109", true);
sendStringAndCheckValidity(addressLevel1Input, "NS", false);
sendStringAndCheckValidity(postalCodeInput, "06390-0001", true);
fillField(countrySelect, "CA");
sendStringAndCheckValidity(postalCodeInput, "00001", false);
sendStringAndCheckValidity(addressLevel1Input, "CA", false);
sendStringAndCheckValidity(postalCodeInput, "94043", false);
sendStringAndCheckValidity(addressLevel1Input, "", false);
sendStringAndCheckValidity(postalCodeInput, "B4N4N4", true);
sendStringAndCheckValidity(addressLevel1Input, "MI", false);
sendStringAndCheckValidity(postalCodeInput, "R3J 3C7", true);
sendStringAndCheckValidity(addressLevel1Input, "", false);
sendStringAndCheckValidity(postalCodeInput, "11109", false);
sendStringAndCheckValidity(addressLevel1Input, "NS", true);
sendStringAndCheckValidity(postalCodeInput, "06390-0001", false);
form.remove();
});
add_task(async function test_merchantShippingAddressErrors() {
let form = new AddressForm();
form.id = "shipping-address-page";
form.setAttribute("selected-state-key", "selectedShippingAddress");
await form.promiseReady;
// Merchant errors only make sense when editing a record so add one.
let address1 = deepClone(PTU.Addresses.TimBR);
address1.guid = "9864798564";
const state = {
page: {
id: "shipping-address-page",
},
"shipping-address-page": {
guid: address1.guid,
},
request: {
paymentDetails: {
shippingAddressErrors: {
addressLine: "Street address needs to start with a D",
city: "City needs to start with a B",
country: "Country needs to start with a C",
dependentLocality: "Can only be SUBURBS, not NEIGHBORHOODS",
organization: "organization needs to start with an A",
phone: "Telephone needs to start with a 9",
postalCode: "Postal code needs to start with a 0",
recipient: "Name needs to start with a Z",
region: "Region needs to start with a Y",
regionCode: "Regions must be 1 to 3 characters in length (sometimes ;) )",
},
},
paymentOptions: {},
},
savedAddresses: {
[address1.guid]: deepClone(address1),
},
};
display.appendChild(form);
await form.requestStore.setState(state);
await asyncElementRendered();
function checkValidationMessage(selector, property) {
let expected = state.request.paymentDetails.shippingAddressErrors[property];
let container = form.form.querySelector(selector + "-container");
ok(!isHidden(container), selector + "-container should be visible");
is(form.form.querySelector(selector).validationMessage,
expected,
"Validation message should match for " + selector);
}
ok(form.saveButton.disabled, "Save button should be disabled due to validation errors");
checkValidationMessage("#street-address", "addressLine");
checkValidationMessage("#address-level2", "city");
checkValidationMessage("#address-level3", "dependentLocality");
checkValidationMessage("#country", "country");
checkValidationMessage("#organization", "organization");
checkValidationMessage("#tel", "phone");
checkValidationMessage("#postal-code", "postalCode");
checkValidationMessage("#given-name", "recipient");
checkValidationMessage("#address-level1", "regionCode");
isnot(form.form.querySelector("#address-level1"),
state.request.paymentDetails.shippingAddressErrors.region,
"When both region and regionCode are supplied we only show the 'regionCode' error");
// TODO: bug 1482808 - the save button should be enabled after editing the fields
form.remove();
});
add_task(async function test_customMerchantValidity_reset() {
let form = new AddressForm();
form.id = "shipping-address-page";
form.setAttribute("selected-state-key", "selectedShippingAddress");
await form.promiseReady;
// Merchant errors only make sense when editing a record so add one.
let address1 = deepClone(PTU.Addresses.TimBL);
address1.guid = "9864798564";
const state = {
page: {
id: "shipping-address-page",
},
"shipping-address-page": {
guid: address1.guid,
},
request: {
paymentDetails: {
shippingAddressErrors: {
addressLine: "Street address needs to start with a D",
city: "City needs to start with a B",
country: "Country needs to start with a C",
organization: "organization needs to start with an A",
phone: "Telephone needs to start with a 9",
postalCode: "Postal code needs to start with a 0",
recipient: "Name needs to start with a Z",
region: "Region needs to start with a Y",
},
},
paymentOptions: {},
},
savedAddresses: {
[address1.guid]: deepClone(address1),
},
};
await form.requestStore.setState(state);
display.appendChild(form);
await asyncElementRendered();
ok(form.querySelectorAll(":-moz-ui-invalid").length > 0, "Check fields are visibly invalid");
info("merchant cleared the errors");
await form.requestStore.setState({
request: {
paymentDetails: {
shippingAddressErrors: {},
},
paymentOptions: {},
},
});
await asyncElementRendered();
is(form.querySelectorAll(":-moz-ui-invalid").length, 0,
"Check fields are visibly valid - custom validity cleared");
form.remove();
});
add_task(async function test_customMerchantValidity_shippingAddressForm() {
let form = new AddressForm();
form.id = "shipping-address-page";
form.setAttribute("selected-state-key", "selectedShippingAddress");
await form.promiseReady;
// Merchant errors only make sense when editing a record so add one.
let address1 = deepClone(PTU.Addresses.TimBL);
address1.guid = "9864798564";
const state = {
page: {
id: "shipping-address-page",
},
"shipping-address-page": {
guid: address1.guid,
},
request: {
paymentDetails: {
billingAddressErrors: {
addressLine: "Billing Street address needs to start with a D",
city: "Billing City needs to start with a B",
country: "Billing Country needs to start with a C",
organization: "Billing organization needs to start with an A",
phone: "Billing Telephone needs to start with a 9",
postalCode: "Billing Postal code needs to start with a 0",
recipient: "Billing Name needs to start with a Z",
region: "Billing Region needs to start with a Y",
},
},
paymentOptions: {},
},
savedAddresses: {
[address1.guid]: deepClone(address1),
},
};
await form.requestStore.setState(state);
display.appendChild(form);
await asyncElementRendered();
is(form.querySelectorAll(":-moz-ui-invalid").length, 0,
"Check fields are visibly valid - billing errors are not relevant to a shipping address form");
// now switch in some shipping address errors
await form.requestStore.setState({
request: {
paymentDetails: {
shippingAddressErrors: {
addressLine: "Street address needs to start with a D",
city: "City needs to start with a B",
country: "Country needs to start with a C",
organization: "organization needs to start with an A",
phone: "Telephone needs to start with a 9",
postalCode: "Postal code needs to start with a 0",
recipient: "Name needs to start with a Z",
region: "Region needs to start with a Y",
},
},
paymentOptions: {},
},
});
await asyncElementRendered();
ok(form.querySelectorAll(":-moz-ui-invalid").length >= 8, "Check fields are visibly invalid");
});
add_task(async function test_customMerchantValidity_billingAddressForm() {
let form = new AddressForm();
form.id = "billing-address-page";
form.setAttribute("selected-state-key", "basic-card-page|billingAddressGUID");
await form.promiseReady;
// Merchant errors only make sense when editing a record so add one.
let address1 = deepClone(PTU.Addresses.TimBL);
address1.guid = "9864798564";
const state = {
page: {
id: "billing-address-page",
},
"billing-address-page": {
guid: address1.guid,
},
request: {
paymentDetails: {
shippingAddressErrors: {
addressLine: "Street address needs to start with a D",
city: "City needs to start with a B",
country: "Country needs to start with a C",
organization: "organization needs to start with an A",
phone: "Telephone needs to start with a 9",
postalCode: "Postal code needs to start with a 0",
recipient: "Name needs to start with a Z",
region: "Region needs to start with a Y",
},
},
paymentOptions: {},
},
savedAddresses: {
[address1.guid]: deepClone(address1),
},
};
await form.requestStore.setState(state);
display.appendChild(form);
await asyncElementRendered();
is(form.querySelectorAll(":-moz-ui-invalid").length, 0,
"Check fields are visibly valid - shipping errors are not relevant to a billing address form");
await form.requestStore.setState({
request: {
paymentDetails: {
paymentMethodErrors: {
billingAddress: {
addressLine: "Billing Street address needs to start with a D",
city: "Billing City needs to start with a B",
country: "Billing Country needs to start with a C",
organization: "Billing organization needs to start with an A",
phone: "Billing Telephone needs to start with a 9",
postalCode: "Billing Postal code needs to start with a 0",
recipient: "Billing Name needs to start with a Z",
region: "Billing Region needs to start with a Y",
},
},
},
paymentOptions: {},
},
});
await asyncElementRendered();
ok(form.querySelectorAll(":-moz-ui-invalid").length >= 8,
"Check billing fields are visibly invalid");
form.remove();
});
add_task(async function test_merchantPayerAddressErrors() {
let form = new AddressForm();
form.id = "payer-address-page";
form.setAttribute("selected-state-key", "selectedPayerAddress");
await form.promiseReady;
form.form.dataset.extraRequiredFields = "name email tel";
// Merchant errors only make sense when editing a record so add one.
let address1 = deepClone(PTU.Addresses.TimBL);
address1.guid = "9864798564";
const state = {
page: {
id: "payer-address-page",
},
"payer-address-page": {
addressFields: "name email tel",
guid: address1.guid,
},
request: {
paymentDetails: {
payerErrors: {
email: "Email must be @mozilla.org",
name: "Name needs to start with a W",
phone: "Telephone needs to start with a 1",
},
},
paymentOptions: {},
},
savedAddresses: {
[address1.guid]: deepClone(address1),
},
};
await form.requestStore.setState(state);
display.appendChild(form);
await asyncElementRendered();
function checkValidationMessage(selector, property) {
is(form.form.querySelector(selector).validationMessage,
state.request.paymentDetails.payerErrors[property],
"Validation message should match for " + selector);
}
ok(form.saveButton.disabled, "Save button should be disabled due to validation errors");
checkValidationMessage("#tel", "phone");
checkValidationMessage("#family-name", "name");
checkValidationMessage("#email", "email");
is(form.querySelectorAll(":-moz-ui-invalid").length, 3, "Check payer fields are visibly invalid");
await form.requestStore.setState({
request: {
paymentDetails: {
payerErrors: {},
},
paymentOptions: {},
},
});
await asyncElementRendered();
is(form.querySelectorAll(":-moz-ui-invalid").length, 0,
"Check payer fields are visibly valid after clearing merchant errors");
form.remove();
});
add_task(async function test_field_validation() {
let getFormFormatStub = sinon.stub(PaymentDialogUtils, "getFormFormat");
getFormFormatStub.returns({
addressLevel1Label: "state",
postalCodeLabel: "US",
fieldsOrder: [
{fieldId: "name", newLine: true},
{fieldId: "organization", newLine: true},
{fieldId: "street-address", newLine: true},
{fieldId: "address-level2"},
],
});
let form = new AddressForm();
form.id = "shipping-address-page";
form.setAttribute("selected-state-key", "selectedShippingAddress");
await form.promiseReady;
const state = {
page: {
id: "shipping-address-page",
},
"shipping-address-page": {
},
request: {
paymentDetails: {
shippingAddressErrors: {},
},
paymentOptions: {},
},
};
await form.requestStore.setState(state);
display.appendChild(form);
await asyncElementRendered();
ok(form.saveButton.disabled, "Save button should be disabled due to empty fields");
let postalCodeInput = form.form.querySelector("#postal-code");
let addressLevel1Input = form.form.querySelector("#address-level1");
ok(!postalCodeInput.value, "postal-code should be empty by default");
ok(!addressLevel1Input.value, "address-level1 should be empty by default");
ok(postalCodeInput.checkValidity(),
"postal-code should be valid by default when it is not visible");
ok(addressLevel1Input.checkValidity(),
"address-level1 should be valid by default when it is not visible");
getFormFormatStub.restore();
form.remove();
});
add_task(async function test_field_validation_dom_popup() {
let form = new AddressForm();
form.id = "shipping-address-page";
form.setAttribute("selected-state-key", "selectedShippingAddress");
await form.promiseReady;
const state = {
page: {
id: "shipping-address-page",
},
"shipping-address-page": {
},
};
await form.requestStore.setState(state);
display.appendChild(form);
await asyncElementRendered();
const BAD_POSTAL_CODE = "hi mom";
let postalCode = form.querySelector("#postal-code");
postalCode.focus();
sendString(BAD_POSTAL_CODE, window);
postalCode.blur();
let errorTextSpan = postalCode.parentNode.querySelector(".error-text");
is(errorTextSpan.textContent, "Please match the requested format.",
"DOM validation messages should be reflected in the error-text #1");
postalCode.focus();
while (postalCode.value) {
sendKey("BACK_SPACE", window);
}
postalCode.blur();
is(errorTextSpan.textContent, "Please fill out this field.",
"DOM validation messages should be reflected in the error-text #2");
postalCode.focus();
sendString("12345", window);
is(errorTextSpan.innerText, "", "DOM validation message should be removed when no error");
postalCode.blur();
form.remove();
});
add_task(async function test_hiddenMailingAddressFieldsCleared() {
let form = new AddressForm();
form.id = "address-page";
form.setAttribute("selected-state-key", "selectedShippingAddress");
form.dataset.updateButtonLabel = "Update";
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",
},
"address-page": {
guid: address1.guid,
},
savedAddresses: {
[address1.guid]: deepClone(address1),
},
});
await asyncElementRendered();
info("Change the country to hide address-level1");
fillField(form.form.querySelector("#country"), "DE");
let expectedRecord = Object.assign({}, address1, {
country: "DE",
// address-level1 & 3 aren't used for Germany so should be blanked.
"address-level1": "",
"address-level3": "",
});
delete expectedRecord.guid;
// The following were not shown so shouldn't be part of the message:
delete expectedRecord.email;
let messagePromise = promiseContentToChromeMessage("updateAutofillRecord");
form.saveButton.scrollIntoView();
synthesizeMouseAtCenter(form.saveButton, {});
info("Waiting for messagePromise");
let details = await messagePromise;
info("/Waiting for messagePromise");
delete details.messageID;
is(details.collectionName, "addresses", "Check collectionName");
isDeeply(details, {
collectionName: "addresses",
guid: address1.guid,
messageType: "updateAutofillRecord",
record: expectedRecord,
}, "Check update event details for the message to chrome");
form.remove();
});
</script>
</body>
</html>