forked from mirrors/gecko-dev
956 lines
32 KiB
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>
|