--- a/browser/components/payments/test/PaymentTestUtils.jsm
+++ b/browser/components/payments/test/PaymentTestUtils.jsm
@@ -79,80 +79,80 @@ var PaymentTestUtils = {
content.showPromise = rq.show();
handle.destruct();
},
},
DialogContentTasks: {
getShippingOptions: () => {
- let select = content.document.querySelector("shipping-option-picker > rich-select");
- let popupBox = Cu.waiveXrays(select).popupBox;
- let selectedOptionIndex = Array.from(popupBox.children)
- .findIndex(item => item.hasAttribute("selected"));
- let selectedOption = popupBox.children[selectedOptionIndex];
- let currencyAmount = selectedOption.querySelector("currency-amount");
+ let picker = content.document.querySelector("shipping-option-picker");
+ let popupBox = Cu.waiveXrays(picker).dropdown.popupBox;
+ let selectedOptionIndex = popupBox.selectedIndex;
+ let selectedOption = Cu.waiveXrays(picker).dropdown.selectedOption;
return {
optionCount: popupBox.children.length,
selectedOptionIndex,
selectedOptionID: selectedOption.getAttribute("value"),
selectedOptionLabel: selectedOption.getAttribute("label"),
- selectedOptionCurrency: currencyAmount.getAttribute("currency"),
- selectedOptionValue: currencyAmount.getAttribute("value"),
+ selectedOptionCurrency: selectedOption.getAttribute("amount-currency"),
+ selectedOptionValue: selectedOption.getAttribute("amount-value"),
};
},
getShippingAddresses: () => {
let doc = content.document;
let addressPicker =
doc.querySelector("address-picker[selected-state-key='selectedShippingAddress']");
- let select = addressPicker.querySelector("rich-select");
- let popupBox = Cu.waiveXrays(select).popupBox;
+ let popupBox = Cu.waiveXrays(addressPicker).dropdown.popupBox;
let options = Array.from(popupBox.children).map(option => {
return {
- guid: option.guid,
- country: option.country,
+ guid: option.getAttribute("guid"),
+ country: option.getAttribute("country"),
selected: option.selected,
};
});
let selectedOptionIndex = options.findIndex(item => item.selected);
return {
selectedOptionIndex,
options,
};
},
- selectShippingAddressByCountry: country => {
+ selectShippingAddressByCountry: (country) => {
let doc = content.document;
let addressPicker =
doc.querySelector("address-picker[selected-state-key='selectedShippingAddress']");
- let select = addressPicker.querySelector("rich-select");
+ let select = Cu.waiveXrays(addressPicker).dropdown.popupBox;
let option = select.querySelector(`[country="${country}"]`);
- select.click();
- option.click();
+ select.focus();
+ // eslint-disable-next-line no-undef
+ EventUtils.synthesizeKey(option.label, {}, content.window);
},
selectShippingAddressByGuid: guid => {
let doc = content.document;
let addressPicker =
doc.querySelector("address-picker[selected-state-key='selectedShippingAddress']");
- let select = addressPicker.querySelector("rich-select");
+ let select = Cu.waiveXrays(addressPicker).dropdown.popupBox;
let option = select.querySelector(`[guid="${guid}"]`);
- select.click();
- option.click();
+ select.focus();
+ // eslint-disable-next-line no-undef
+ EventUtils.synthesizeKey(option.label, {}, content.window);
},
selectShippingOptionById: value => {
let doc = content.document;
let optionPicker =
doc.querySelector("shipping-option-picker");
- let select = optionPicker.querySelector("rich-select");
+ let select = Cu.waiveXrays(optionPicker).dropdown.popupBox;
let option = select.querySelector(`[value="${value}"]`);
- select.click();
- option.click();
+ select.focus();
+ // eslint-disable-next-line no-undef
+ EventUtils.synthesizeKey(option.textContent, {}, content.window);
},
/**
* Click the cancel button
*
* Don't await on this task since the cancel can close the dialog before
* ContentTask can resolve the promise.
*
--- a/browser/components/payments/test/browser/browser_address_edit.js
+++ b/browser/components/payments/test/browser/browser_address_edit.js
@@ -116,18 +116,18 @@ add_task(async function test_edit_link()
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
let {tempAddresses, savedAddresses} = await PTU.DialogContentUtils.getCurrentState(content);
is(Object.keys(tempAddresses).length, 0, "No temporary addresses at the start of test");
is(Object.keys(savedAddresses).length, 1, "1 saved address at the start of test");
let picker = content.document
.querySelector("address-picker[selected-state-key='selectedShippingAddress']");
- Cu.waiveXrays(picker).dropdown.click();
- Cu.waiveXrays(picker).dropdown.popupBox.children[0].click();
+ Cu.waiveXrays(picker).dropdown.popupBox.focus();
+ EventUtils.synthesizeKey(PTU.Addresses.TimBL["given-name"], {}, content.window);
let editLink = content.document.querySelector("address-picker .edit-link");
is(editLink.textContent, "Edit", "Edit link text");
editLink.click();
await PTU.DialogContentUtils.waitForState(content, (state) => {
return state.page.id == "address-page" && !!state["address-page"].guid;
--- a/browser/components/payments/test/browser/head.js
+++ b/browser/components/payments/test/browser/head.js
@@ -259,16 +259,17 @@ async function setupPaymentDialog(browse
info("dialog ready");
await spawnPaymentDialogTask(frame, () => {
let elementHeight = (element) =>
element.getBoundingClientRect().height;
content.isHidden = (element) => elementHeight(element) == 0;
content.isVisible = (element) => elementHeight(element) > 0;
});
+ await injectEventUtilsInContentTask(frame);
info("helper functions injected into frame");
return {win, requestId, frame};
}
/**
* Open a merchant tab with the given merchantTaskFn to create a PaymentRequest
* and then open the associated PaymentRequest dialog in a new tab and run the
@@ -483,8 +484,45 @@ async function fillInCardForm(frame, aCa
}
let persistCheckbox = content.document.querySelector(options.checkboxSelector);
// only touch the checked state if explicitly told to in the options
if (options.hasOwnProperty("isTemporary")) {
Cu.waiveXrays(persistCheckbox).checked = !options.isTemporary;
}
}, {card: aCard, options: aOptions});
}
+
+// The JSDoc validator does not support @returns tags in abstract functions or
+// star functions without return statements.
+/* eslint-disable valid-jsdoc */
+/**
+ * Inject `EventUtils` helpers into ContentTask scope.
+ *
+ * This helper is automatically exposed to mochitest browser tests,
+ * but is missing from content task scope.
+ * You should call this method only once per <browser> tag
+ *
+ * @param {xul:browser} browser
+ * Reference to the browser in which we load content task
+ */
+/* eslint-enable valid-jsdoc */
+async function injectEventUtilsInContentTask(browser) {
+ await ContentTask.spawn(browser, {}, async function() {
+ if ("EventUtils" in this) {
+ return;
+ }
+
+ const EventUtils = this.EventUtils = {};
+
+ EventUtils.window = {};
+ EventUtils.parent = EventUtils.window;
+ /* eslint-disable camelcase */
+ EventUtils._EU_Ci = Ci;
+ EventUtils._EU_Cc = Cc;
+ /* eslint-enable camelcase */
+ // EventUtils' `sendChar` function relies on the navigator to synthetize events.
+ EventUtils.navigator = content.navigator;
+ EventUtils.KeyboardEvent = content.KeyboardEvent;
+
+ Services.scriptloader.loadSubScript(
+ "chrome://mochikit/content/tests/SimpleTest/EventUtils.js", EventUtils);
+ });
+}
--- a/browser/components/payments/test/mochitest/test_address_form.html
+++ b/browser/components/payments/test/mochitest/test_address_form.html
@@ -154,16 +154,17 @@ add_task(async function test_saveButton(
},
},
guid: undefined,
messageType: "updateAutofillRecord",
preserveOldProperties: true,
record: {
"given-name": "Jaws",
"family-name": "Swaj",
+ "additional-name": "",
"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",
--- a/browser/components/payments/test/mochitest/test_address_picker.html
+++ b/browser/components/payments/test/mochitest/test_address_picker.html
@@ -64,18 +64,18 @@ add_task(async function test_initialSet(
"street-address": "P.O. Box 123",
"tel": "+1 650 555-5555",
},
},
});
await asyncElementRendered();
let options = picker1.dropdown.popupBox.children;
is(options.length, 2, "Check dropdown has both addresses");
- ok(options[0].textContent.includes("123 Sesame Street"), "Check first address");
- ok(options[1].textContent.includes("P.O. Box 123"), "Check second address");
+ ok(options[0].textContent.includes("Mr. Foo"), "Check first address");
+ ok(options[1].textContent.includes("Mrs. Bar"), "Check second address");
});
add_task(async function test_update() {
picker1.requestStore.setState({
savedAddresses: {
"48bnds6854t": {
// Same GUID, different values to trigger an update
"address-level1": "MI-edit",
@@ -97,38 +97,48 @@ add_task(async function test_update() {
"street-address": "P.O. Box 123",
"tel": "+1 650 555-5555",
},
},
});
await asyncElementRendered();
let options = picker1.dropdown.popupBox.children;
is(options.length, 2, "Check dropdown still has both addresses");
- ok(options[0].textContent.includes("MI-edit"), "Check updated first address-level1");
- ok(!options[0].textContent.includes("Some City"), "Check removed first address-level2");
- ok(options[0].textContent.includes("new-edit"), "Check updated first address");
-
- ok(options[1].textContent.includes("P.O. Box 123"), "Check second address is the same");
+ ok(options[0].textContent.includes("Mr. Foo-edit"), "Check updated name in first address");
+ ok(!options[0].getAttribute("address-level2"), "Check removed first address-level2");
+ ok(options[1].textContent.includes("Mrs. Bar"), "Check that name is the same in second address");
+ ok(options[1].getAttribute("street-address").includes("P.O. Box 123"),
+ "Check second address is the same");
});
add_task(async function test_change_selected_address() {
let options = picker1.dropdown.popupBox.children;
- let selectedOption = picker1.dropdown.selectedOption;
- is(selectedOption, null, "Should default to no selected option");
+ is(picker1.dropdown.selectedOption, null, "Should default to no selected option");
let {selectedShippingAddress} = picker1.requestStore.getState();
is(selectedShippingAddress, null, "store should have no option selected");
- picker1.dropdown.click();
- options[1].click();
+ picker1.dropdown.popupBox.focus();
+ synthesizeKey(options[1].getAttribute("name"), {});
await asyncElementRendered();
- selectedOption = picker1.dropdown.selectedOption;
+ let selectedOption = picker1.dropdown.selectedOption;
is(selectedOption, options[1], "Selected option should now be the second option");
selectedShippingAddress = picker1.requestStore.getState().selectedShippingAddress;
- is(selectedShippingAddress, selectedOption.guid, "store should have second option selected");
+ is(selectedShippingAddress, selectedOption.getAttribute("guid"),
+ "store should have second option selected");
+});
+
+add_task(async function test_streetAddress_combines_street_level2_level1_postalCode_country() {
+ let options = picker1.dropdown.popupBox.children;
+ let richoption1 = picker1.dropdown.querySelector(".rich-select-selected-option");
+ let streetAddress = richoption1.querySelector(".street-address");
+ /* eslint-disable max-len */
+ is(streetAddress.textContent,
+ `${options[1].getAttribute("street-address")} ${options[1].getAttribute("address-level2")} ${options[1].getAttribute("address-level1")} ${options[1].getAttribute("postal-code")} ${options[1].getAttribute("country")}`);
+ /* eslint-enable max-len */
});
add_task(async function test_delete() {
picker1.requestStore.setState({
savedAddresses: {
// 48bnds6854t was deleted
"68gjdh354j": {
"address-level1": "CA",
@@ -140,14 +150,14 @@ add_task(async function test_delete() {
"street-address": "P.O. Box 123",
"tel": "+1 650 555-5555",
},
},
});
await asyncElementRendered();
let options = picker1.dropdown.popupBox.children;
is(options.length, 1, "Check dropdown has one remaining address");
- ok(options[0].textContent.includes("P.O. Box 123"), "Check remaining address");
+ ok(options[0].textContent.includes("Mrs. Bar"), "Check remaining address");
});
</script>
</body>
</html>
--- a/browser/components/payments/test/mochitest/test_basic_card_form.html
+++ b/browser/components/payments/test/mochitest/test_basic_card_form.html
@@ -123,16 +123,17 @@ add_task(async function test_saveButton(
guid: undefined,
messageType: "updateAutofillRecord",
preserveOldProperties: true,
record: {
"cc-exp-month": "11",
"cc-exp-year": year,
"cc-name": "J. Smith",
"cc-number": "4111111111111111",
+ "billingAddressGUID": "",
},
selectedStateKey: ["selectedPaymentCard"],
successStateChange: {
page: {
id: "payment-summary",
},
},
}, "Check event details for the message to chrome");
--- a/browser/components/payments/test/mochitest/test_payer_address_picker.html
+++ b/browser/components/payments/test/mochitest/test_payer_address_picker.html
@@ -27,23 +27,16 @@ Test the paymentOptions address-picker
</div>
<pre id="test">
</pre>
<script type="module">
/** Test the payer requested details functionality **/
import PaymentDialog from "../../res/containers/payment-dialog.js";
-function getVisiblePickerOptions(picker) {
- let select = picker.querySelector(":scope > rich-select");
- let options = select.querySelectorAll("address-option");
- let visibleOptions = Array.from(options).filter(isVisible);
- return visibleOptions;
-}
-
function isVisible(elem) {
let result = elem.getBoundingClientRect().height > 0;
return result;
}
function setPaymentOptions(requestStore, options) {
let {request} = requestStore.getState();
request = Object.assign({}, request, {
@@ -181,29 +174,27 @@ add_task(async function test_visible_fie
requestStore.setState({
savedAddresses: SAVED_ADDRESSES,
selectedPayerAddress: "48bnds6854t",
});
await asyncElementRendered();
- let visibleOptions = getVisiblePickerOptions(elPicker);
- let visibleOption = visibleOptions[0];
-
+ let closedRichOption = elPicker.dropdown.querySelector(".rich-select-selected-option");
is(elPicker.dropdown.popupBox.children.length, 2, "Check dropdown has 2 addresses");
- is(visibleOptions.length, 1, "One option should be visible");
- is(visibleOption.getAttribute("guid"), "48bnds6854t", "expected option is visible");
+ is(closedRichOption.getAttribute("guid"), "48bnds6854t", "expected option is visible");
for (let fieldName of ["name", "email", "tel"]) {
- let elem = visibleOption.querySelector(`.${fieldName}`);
+ let elem = closedRichOption.querySelector(`.${fieldName}`);
ok(elem, `field ${fieldName} exists`);
ok(isVisible(elem), `field ${fieldName} is visible`);
}
- ok(!isVisible(visibleOption.querySelector(".street-address")), "street-address is not visible");
+ ok(!isVisible(closedRichOption.querySelector(".street-address")),
+ "street-address is not visible");
});
add_task(async function test_selective_fields() {
await setup();
let requestStore = elPicker.requestStore;
requestStore.setState({
savedAddresses: SAVED_ADDRESSES,
@@ -218,20 +209,20 @@ add_task(async function test_selective_f
{requestPayerName: false, requestPayerEmail: true, requestPayerPhone: true },
{requestPayerName: true, requestPayerEmail: false, requestPayerPhone: true },
];
for (let payerFields of payerFieldVariations) {
setPaymentOptions(requestStore, payerFields);
await asyncElementRendered();
- let visibleOption = getVisiblePickerOptions(elPicker)[0];
- let elName = visibleOption.querySelector(".name");
- let elEmail = visibleOption.querySelector(".email");
- let elPhone = visibleOption.querySelector(".tel");
+ let closedRichOption = elPicker.dropdown.querySelector(".rich-select-selected-option");
+ let elName = closedRichOption.querySelector(".name");
+ let elEmail = closedRichOption.querySelector(".email");
+ let elPhone = closedRichOption.querySelector(".tel");
is(isVisible(elName), payerFields.requestPayerName,
"name field is correctly toggled");
is(isVisible(elEmail), payerFields.requestPayerEmail,
"email field is correctly toggled");
is(isVisible(elPhone), payerFields.requestPayerPhone,
"tel field is correctly toggled");
}
@@ -247,42 +238,37 @@ add_task(async function test_filtered_op
requestStore.setState({
savedAddresses: DUPED_ADDRESSES,
selectedPayerAddress: "a9e830667189",
});
await asyncElementRendered();
- let visibleOptions = getVisiblePickerOptions(elPicker);
- let visibleOption = visibleOptions[0];
-
- is(elPicker.dropdown.popupBox.children.length, 4, "Check dropdown has 3 addresses");
- is(visibleOptions.length, 1, "One option should be visible");
- is(visibleOption.getAttribute("guid"), "a9e830667189", "expected option is visible");
+ let closedRichOption = elPicker.dropdown.querySelector(".rich-select-selected-option");
+ is(elPicker.dropdown.popupBox.children.length, 4, "Check dropdown has 4 addresses");
+ is(closedRichOption.getAttribute("guid"), "a9e830667189", "expected option is visible");
for (let fieldName of ["name", "email"]) {
- let elem = visibleOption.querySelector(`.${fieldName}`);
+ let elem = closedRichOption.querySelector(`.${fieldName}`);
ok(elem, `field ${fieldName} exists`);
ok(isVisible(elem), `field ${fieldName} is visible`);
}
setPaymentOptions(requestStore, {
requestPayerPhone: true,
});
await asyncElementRendered();
is(elPicker.dropdown.popupBox.children.length, 1, "Check dropdown has 1 addresses");
- is(visibleOptions.length, 1, "One option should be visible");
setPaymentOptions(requestStore, {});
await asyncElementRendered();
is(elPicker.dropdown.popupBox.children.length, 4, "Check dropdown has 4 addresses");
- is(visibleOptions.length, 1, "One option should be visible");
});
add_task(async function test_no_matches() {
await setup();
let requestStore = elPicker.requestStore;
setPaymentOptions(requestStore, {
requestPayerPhone: true,
});
@@ -299,17 +285,17 @@ add_task(async function test_no_matches(
"name": "Rita Foo",
},
},
selectedPayerAddress: "a9e830667189",
});
await asyncElementRendered();
- let visibleOptions = getVisiblePickerOptions(elPicker);
+ let closedRichOption = elPicker.dropdown.querySelector(".rich-select-selected-option");
is(elPicker.dropdown.popupBox.children.length, 0, "Check dropdown is empty");
- is(visibleOptions.length, 0, "No options should be visible");
+ ok(closedRichOption.localName !== "address-option", "No option is selected and visible");
});
</script>
</body>
</html>
--- a/browser/components/payments/test/mochitest/test_payment_method_picker.html
+++ b/browser/components/payments/test/mochitest/test_payment_method_picker.html
@@ -99,46 +99,43 @@ add_task(async function test_update() {
ok(options[0].textContent.includes("9876"), "Check updated first cc-number");
ok(options[0].textContent.includes("09"), "Check updated first exp-month");
ok(options[1].textContent.includes("J Smith"), "Check second card is the same");
});
add_task(async function test_change_selected_card() {
let options = picker1.dropdown.popupBox.children;
- let selectedOption = picker1.dropdown.selectedOption;
- is(selectedOption, null, "Should default to no selected option");
+ is(picker1.dropdown.selectedOption, null, "Should default to no selected option");
let {
selectedPaymentCard,
selectedPaymentCardSecurityCode,
} = picker1.requestStore.getState();
is(selectedPaymentCard, null, "store should have no option selected");
is(selectedPaymentCardSecurityCode, null, "store should have no security code");
await SimpleTest.promiseFocus();
- let codeFocusPromise = new Promise(resolve => {
- picker1.securityCodeInput.addEventListener("focus", resolve, {once: true});
- });
- picker1.dropdown.click();
- options[1].click();
+ picker1.dropdown.popupBox.focus();
+ synthesizeKey("************1234", {});
await asyncElementRendered();
- await codeFocusPromise;
ok(true, "Focused the security code field");
ok(!picker1.open, "Picker should be closed");
- selectedOption = picker1.dropdown.selectedOption;
+ let selectedOption = picker1.dropdown.selectedOption;
is(selectedOption, options[1], "Selected option should now be the second option");
selectedPaymentCard = picker1.requestStore.getState().selectedPaymentCard;
- is(selectedPaymentCard, selectedOption.guid, "store should have second option selected");
+ is(selectedPaymentCard, selectedOption.getAttribute("guid"),
+ "store should have second option selected");
selectedPaymentCardSecurityCode = picker1.requestStore.getState().selectedPaymentCardSecurityCode;
is(selectedPaymentCardSecurityCode, null, "store should have empty security code");
let stateChangePromise = promiseStateChange(picker1.requestStore);
// Type in the security code field
+ picker1.securityCodeInput.focus();
sendString("836");
sendKey("Tab");
let state = await stateChangePromise;
ok(state.selectedPaymentCardSecurityCode, "836", "Check security code in state");
});
add_task(async function test_delete() {
picker1.requestStore.setState({
--- a/browser/components/payments/test/mochitest/test_rich_select.html
+++ b/browser/components/payments/test/mochitest/test_rich_select.html
@@ -14,358 +14,128 @@ Test the rich-select component
<link rel="stylesheet" type="text/css" href="../../res/components/rich-select.css"/>
<link rel="stylesheet" type="text/css" href="../../res/components/address-option.css"/>
<link rel="stylesheet" type="text/css" href="../../res/components/basic-card-option.css"/>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<p id="display">
- <rich-select id="select1">
- <!-- the class="rich-option" is required to be hard-coded due to a bug with the custom
- elements polyfill causing the address-option constructor to happen too late. -->
- <address-option id="option1"
- class="rich-option"
- email="emzembrano92@email.com"
- name="Emily Zembrano"
- street-address="717 Hyde Street #6"
- address-level2="San Francisco"
- address-level1="CA"
- tel="415 203 0845"
- postal-code="94109"
- country="USA"></address-option>
- <address-option id="option2"
- class="rich-option"
- email="jenz9382@email.com"
- name="Jennifer Zembrano"
- street-address="42 Fairydust Lane"
- address-level2="Lala Land"
- address-level1="HI"
- tel="415 439 2827"
- postal-code="98765"
- country="USA"></address-option>
- <address-option id="option3"
- class="rich-option"
- email="johnz9382@email.com"
- name="John Zembrano"
- street-address="42 Fairydust Lane"
- address-level2="Lala Land"
- missinginformation="true"
- address-level1="HI"
- tel="415 439 2827"
- postal-code="98765"
- country="USA"></address-option>
- </rich-select>
-
- <rich-select id="select2">
- <basic-card-option cc-name="Jared Wein"
- class="rich-option"
- cc-exp="1970-01"
- cc-number="************3599"
- type="Visa"></basic-card-option>
- <basic-card-option cc-name="Whimsy Corn"
- class="rich-option"
- cc-exp="1970-01"
- cc-number="*************7667"
- type="Mastercard"></basic-card-option>
- <basic-card-option cc-name="Fire Fox"
- class="rich-option"
- cc-exp="1970-01"
- cc-number="************1054"
- type="Discover"></basic-card-option>
- </rich-select>
</p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
<script type="module">
/** Test the rich-select address-option component **/
import AddressOption from "../../res/components/address-option.js";
-import BasicCardOption from "../../res/components/basic-card-option.js";
import RichSelect from "../../res/components/rich-select.js";
-let select1 = document.getElementById("select1");
-let option1 = document.getElementById("option1");
-let option2 = document.getElementById("option2");
-let option3 = document.getElementById("option3");
+let addresses = {
+ "58gjdh354k": {
+ "email": "emzembrano92@email.com",
+ "name": "Emily Zembrano",
+ "street-address": "717 Hyde Street #6",
+ "address-level2": "San Francisco",
+ "address-level1": "CA",
+ "tel": "415 203 0845",
+ "postal-code": "94109",
+ "country": "USA",
+ "guid": "58gjdh354k",
+ },
+ "67gjdh354k": {
+ "email": "jenz9382@email.com",
+ "name": "Jennifer Zembrano",
+ "street-address": "42 Fairydust Lane",
+ "address-level2": "Lala Land",
+ "address-level1": "HI",
+ "tel": "415 439 2827",
+ "postal-code": "98765",
+ "country": "USA",
+ "guid": "67gjdh354k",
+ },
+};
+
+let select1 = new RichSelect();
+for (let address of Object.values(addresses)) {
+ let option = document.createElement("option");
+ option.textContent = address.name + " " + address["street-address"];
+ option.setAttribute("value", address.guid);
+ for (let field of Object.keys(address)) {
+ option.setAttribute(field, address[field]);
+ }
+ select1.popupBox.appendChild(option);
+}
+select1.setAttribute("option-type", "address-option");
+select1.value = "";
+document.getElementById("display").appendChild(select1);
+
+let options = select1.popupBox.children;
+let option1 = options[0];
+let option2 = options[1];
function get_selected_clone() {
- return select1.querySelector(".rich-select-selected-clone");
+ return select1.querySelector(".rich-select-selected-option");
}
function is_visible(element, message) {
ok(!isHidden(element), message);
}
-function is_hidden(element, message) {
- ok(isHidden(element), message);
-}
-
-function dispatchKeyDown(key, keyCode) {
- select1.dispatchEvent(new KeyboardEvent("keydown", {key, keyCode}));
-}
-
-add_task(async function test_streetAddress_combines_street_level2_level1_postalCode_country() {
- ok(option1, "option1 exists");
- let streetAddress = option1.querySelector(".street-address");
- /* eslint-disable max-len */
- is(streetAddress.textContent,
- `${option1.streetAddress} ${option1.addressLevel2} ${option1.addressLevel1} ${option1.postalCode} ${option1.country}`);
- /* eslint-enable max-len */
-});
-
-add_task(async function test_no_option_selected() {
+add_task(async function test_closed_state_on_selection() {
ok(select1, "select1 exists");
-
+ select1.popupBox.focus();
+ synthesizeKey(option1.textContent, {});
await asyncElementRendered();
-
- is_hidden(option1, "option 1 should be hidden when popup is not open");
- is_hidden(option2, "option 2 should be hidden when popup is not open");
- is_hidden(option3, "option 3 should be hidden when popup is not open");
- ok(!option1.selected, "option 1 should not be selected");
- ok(!option1.hasAttribute("selected"), "option 1 should not have selected attribute");
- let selectedClone = get_selected_clone();
- is_visible(selectedClone, "The selected clone should be visible at all times");
- ok(selectedClone.classList.contains("rich-option"), "Default option should be a rich-option");
- ok(selectedClone.textContent.includes("None selected"), "Check default text");
-});
-
-add_task(async function test_clicking_on_select_shows_all_options() {
- ok(select1, "select1 exists");
- ok(!select1.open, "select is not open by default");
- ok(!option1.selected, "option 1 should not be selected by default");
-
- select1.click();
-
- ok(select1.open, "select is open after clicking on it");
- is(select1.selectedOption, null, "No selected option when open");
- ok(!option1.selected, "option 1 should not be selected when open");
- is_visible(option1, "option 1 is visible when select is open");
- is_visible(option2, "option 2 is visible when select is open");
- is_visible(option3, "option 3 is visible when select is open");
-
- option2.click();
-
- ok(!select1.open, "select is not open after blur");
- ok(!option1.selected, "option 1 is not selected after click on option 2");
- ok(option2.selected, "option 2 is selected after clicking on it");
- is_hidden(option1, "option 1 is hidden when select is closed");
- is_hidden(option2, "option 2 is hidden when select is closed");
- is_hidden(option3, "option 3 is hidden when select is closed");
-
- await asyncElementRendered();
+ ok(option1.selected, "option 1 is now selected");
let selectedClone = get_selected_clone();
is_visible(selectedClone, "The selected clone should be visible at all times");
- is(selectedClone.getAttribute("email"), option2.getAttribute("email"),
+ is(selectedClone.getAttribute("email"), option1.getAttribute("email"),
"The selected clone email should be equivalent to the selected option 2");
- is(selectedClone.getAttribute("name"), option2.getAttribute("name"),
+ is(selectedClone.getAttribute("name"), option1.getAttribute("name"),
"The selected clone name should be equivalent to the selected option 2");
});
-add_task(async function test_changing_option_selected_affects_other_options() {
- ok(option2.selected, "Option 2 should be selected from prior test");
-
- select1.selectedOption = option1;
- ok(!option2.selected, "Option 2 should no longer be selected after making option 1 selected");
- ok(option1.hasAttribute("selected"), "Option 1 should now have selected attribute");
-});
-
-add_task(async function test_up_down_keys_change_selected_item() {
- let openObserver = new MutationObserver(mutations => {
- for (let mutation of mutations) {
- ok(mutation.attributeName != "open", "the select should not open/close during this test");
- }
- });
- openObserver.observe(select1, {attributes: true});
-
- ok(select1, "select1 exists");
- ok(option1.selected, "option 1 should be selected by default");
-
- ok(!select1.open, "select should not be open before focusing");
- select1.focus();
- ok(!select1.open, "select should not be open after focusing");
-
- dispatchKeyDown("ArrowDown", 40);
- ok(!option1.selected, "option 1 should no longer be selected");
- ok(option2.selected, "option 2 should now be selected");
-
- dispatchKeyDown("ArrowDown", 40);
- ok(!option2.selected, "option 2 should no longer be selected");
- ok(option3.selected, "option 3 should now be selected");
-
- dispatchKeyDown("ArrowDown", 40);
- ok(option3.selected, "option 3 should remain selected");
- ok(!option1.selected, "option 1 should not be selected");
-
- dispatchKeyDown("ArrowUp", 38);
- ok(!option3.selected, "option 3 should no longer be selected");
- ok(option2.selected, "option 2 should now be selected");
-
- dispatchKeyDown("ArrowUp", 38);
- ok(!option2.selected, "option 2 should no longer be selected");
- ok(option1.selected, "option 1 should now be selected");
-
- dispatchKeyDown("ArrowUp", 38);
- ok(option1.selected, "option 1 should remain selected");
- ok(!option3.selected, "option 3 should not be selected");
-
- // Wait for any mutation observer notifications to fire before exiting.
- await Promise.resolve();
+add_task(async function test_multi_select_not_supported_in_dropdown() {
+ ok(option1.selected, "Option 1 should be selected from prior test");
- openObserver.disconnect();
-});
-
-add_task(async function test_open_close_from_keyboard() {
- select1.focus();
-
- ok(!select1.open, "select should not be open by default");
-
- dispatchKeyDown(" ", 32);
- ok(select1.open, "select should now be open");
- ok(option1.selected, "option 1 should be selected by default");
-
- dispatchKeyDown("ArrowDown", 40);
- ok(!option1.selected, "option 1 should not be selected");
- ok(option2.selected, "option 2 should now be selected");
- ok(select1.open, "select should remain open");
-
- dispatchKeyDown("ArrowUp", 38);
- ok(option1.selected, "option 1 should now be selected");
- ok(!option2.selected, "option 2 should not be selected");
- ok(select1.open, "select should remain open");
-
- dispatchKeyDown("Enter", 13);
- ok(option1.selected, "option 1 should now be selected");
- ok(!select1.open, "select should be closed");
+ select1.popupBox.focus();
+ synthesizeKey(option2.textContent, {});
+ await asyncElementRendered();
- dispatchKeyDown(" ", 32);
- ok(select1.open, "select should now be open");
-
- dispatchKeyDown("Escape", 27);
- ok(!select1.open, "select should be closed");
-});
-
-add_task(async function test_clicking_on_options_maintain_one_item_always_selected() {
- ok(!select1.open, "select should be closed by default");
- ok(option1.selected, "option 1 should be selected by default");
- select1.click();
- ok(select1.open, "select should now be open");
-
- option3.click();
- ok(!select1.open, "select should be closed");
- ok(!option1.selected, "option 1 should be unselected");
- ok(option3.selected, "option 3 should be selected");
-
- select1.click();
- ok(select1.open, "select should open");
- ok(!option1.selected, "option 1 should be unselected");
- ok(option3.selected, "option 3 should be selected");
-
- option1.click();
- ok(!select1.open, "select should be closed");
- ok(option1.selected, "option 1 should be selected");
- ok(!option3.selected, "option 3 should be unselected");
+ ok(!option1.selected, "Option 1 should no longer be selected after selecting option1");
+ ok(option2.selected, "Option 2 should now have selected property set to true");
});
add_task(async function test_selected_clone_should_equal_selected_option() {
- ok(option1.selected, "option 1 should be selected");
- await asyncElementRendered();
+ ok(option2.selected, "option 2 should be selected");
- let clonedOptions = select1.querySelectorAll(".rich-select-selected-clone");
+ let clonedOptions = select1.querySelectorAll(".rich-select-selected-option");
is(clonedOptions.length, 1, "there should only be one cloned option");
let clonedOption = clonedOptions[0];
- for (let attrName of AddressOption.observedAttributes) {
- if (attrName == "selected") {
- continue;
- }
+ for (let attrName of AddressOption.recordAttributes) {
+ is(clonedOption.attributes[attrName] && clonedOption.attributes[attrName].value,
+ option2.attributes[attrName] && option2.attributes[attrName].value,
+ "attributes should have matching value; name=" + attrName);
+ }
+
+ select1.popupBox.focus();
+ synthesizeKey(option1.textContent, {});
+ await asyncElementRendered();
+
+ clonedOptions = select1.querySelectorAll(".rich-select-selected-option");
+ is(clonedOptions.length, 1, "there should only be one cloned option");
+
+ clonedOption = clonedOptions[0];
+ for (let attrName of AddressOption.recordAttributes) {
is(clonedOption.attributes[attrName] && clonedOption.attributes[attrName].value,
option1.attributes[attrName] && option1.attributes[attrName].value,
"attributes should have matching value; name=" + attrName);
}
-
- select1.selectedOption = option2;
- await asyncElementRendered();
-
- clonedOptions = select1.querySelectorAll(".rich-select-selected-clone");
- is(clonedOptions.length, 1, "there should only be one cloned option");
-
- clonedOption = clonedOptions[0];
- for (let attrName of AddressOption.observedAttributes) {
- if (attrName == "selected") {
- continue;
- }
- is(clonedOption.attributes[attrName] && clonedOption.attributes[attrName].value,
- option2.attributes[attrName] && option2.attributes[attrName].value,
- "attributes should have matching value; name=" + attrName);
- }
});
-
-add_task(async function test_basic_card_simple() {
- let select2 = document.getElementById("select2");
- ok(select2, "basic card select should exist");
- let popupBox = select2.querySelector(".rich-select-popup-box");
- ok(popupBox, "basic card popup box exists");
-
- is(popupBox.childElementCount, 3, "There should be three children in the popup box");
-
- select2.selectedOption = popupBox.firstElementChild;
- await asyncElementRendered();
-
- let clonedOption = select2.querySelector(".rich-select-selected-clone");
- let selectedOption = popupBox.firstElementChild;
- for (let attrName of BasicCardOption.observedAttributes) {
- if (attrName == "selected") {
- continue;
- }
- is(clonedOption.attributes[attrName] && clonedOption.attributes[attrName].value,
- selectedOption.attributes[attrName] && selectedOption.attributes[attrName].value,
- "attributes should have matching value; name=" + attrName);
- }
-});
-
-add_task(async function test_option_appended_after_creation() {
- let select2 = document.getElementById("select2");
- let select3 = new RichSelect();
- select3.id = "select3";
- select2.parentNode.insertBefore(select3, select2.nextElementSibling);
-
- is(select3.childElementCount, 2, "There should be a popup child and clone");
- let popupBox = select3.querySelector(".rich-select-popup-box");
- ok(popupBox, "The popup box should exist");
- is(popupBox.childElementCount, 0, "The popup should not have any children");
-
- let newOption = new AddressOption();
- newOption.name = "Jared FooBar";
- select3.appendChild(newOption);
- await asyncElementRendered();
-
- is(select3.childElementCount, 2, "There should now be two children");
- is(popupBox.childElementCount, 1, "The popup box should have one child");
- ok(!popupBox.children[0].selected, "The only option should not be marked selected");
- is(select3.selectedOption, null, "Check there is no selected option");
- let clonedOption = select3.querySelector(".rich-select-selected-clone");
- ok(clonedOption, "cloned option exists");
-
- // Select the new option
- select3.selectedOption = popupBox.lastElementChild;
- await asyncElementRendered();
-
- clonedOption = select3.querySelector(".rich-select-selected-clone");
- is(clonedOption.name, "Jared FooBar", "Check cloned name");
-
- newOption.remove();
- await asyncElementRendered();
-
- is(select3.childElementCount, 2, "There should still be two children");
- is(popupBox.childElementCount, 0, "The popup box should not have any children");
- clonedOption = select3.querySelector(".rich-select-selected-clone");
- todo(clonedOption.textContent.includes("None selected"), "the dropdown should show no selection");
-});
-
</script>
</body>
</html>
--- a/browser/components/payments/test/mochitest/test_shipping_option_picker.html
+++ b/browser/components/payments/test/mochitest/test_shipping_option_picker.html
@@ -68,21 +68,21 @@ add_task(async function test_initialSet(
},
},
selectedShippingOption: "456",
});
await asyncElementRendered();
let options = picker1.dropdown.popupBox.children;
is(options.length, 2, "Check dropdown has both options");
ok(options[0].textContent.includes("Carrier Pigeon"), "Check first option");
- is(options[0].querySelector(".amount").currency, "USD", "Check currency");
+ is(options[0].getAttribute("amount-currency"), "USD", "Check currency");
ok(options[1].textContent.includes("Lightspeed (default)"), "Check second option");
is(picker1.dropdown.selectedOption, options[1], "Lightspeed selected by default");
- let selectedClone = picker1.dropdown.querySelector(".rich-select-selected-clone");
+ let selectedClone = picker1.dropdown.querySelector(".rich-select-selected-option");
let text = selectedClone.textContent;
ok(text.includes("$20.00"),
"Shipping option clone should include amount. Value = " + text);
ok(text.includes("Lightspeed (default)"),
"Shipping option clone should include label. Value = " + text);
ok(!isHidden(selectedClone),
"Shipping option clone should be visible");
});
@@ -115,34 +115,34 @@ add_task(async function test_update() {
},
selectedShippingOption: "456",
});
await promiseStateChange(picker1.requestStore);
let options = picker1.dropdown.popupBox.children;
is(options.length, 2, "Check dropdown still has both options");
ok(options[0].textContent.includes("Tortoise"), "Check updated first option");
- is(options[0].querySelector(".amount").currency, "CAD", "Check currency");
+ is(options[0].getAttribute("amount-currency"), "CAD", "Check currency");
ok(options[1].textContent.includes("Lightspeed (default)"), "Check second option is the same");
is(picker1.dropdown.selectedOption, options[1], "Lightspeed selected by default");
});
add_task(async function test_change_selected_option() {
let options = picker1.dropdown.popupBox.children;
let selectedOption = picker1.dropdown.selectedOption;
is(options[1], selectedOption, "Should default to Lightspeed option");
is(selectedOption.value, "456", "Selected option should have correct ID");
let state = picker1.requestStore.getState();
let selectedOptionFromState = state.selectedShippingOption;
is(selectedOption.value, selectedOptionFromState,
"store's selected option should match selected element");
let stateChangedPromise = promiseStateChange(picker1.requestStore);
- picker1.dropdown.click();
- options[0].click();
+ picker1.dropdown.popupBox.focus();
+ synthesizeKey(options[0].textContent, {});
state = await stateChangedPromise;
selectedOption = picker1.dropdown.selectedOption;
is(selectedOption, options[0], "Selected option should now be the first option");
is(selectedOption.value, "123", "Selected option should have correct ID");
selectedOptionFromState = state.selectedShippingOption;
is(selectedOptionFromState, "123", "store should have first option selected");
});