forked from mirrors/gecko-dev
Bug 1470199 - Add a tooltip for the CVV input. r=MattN
Differential Revision: https://phabricator.services.mozilla.com/D7473 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
6309162ed8
commit
4a3b48e09b
17 changed files with 277 additions and 46 deletions
103
browser/components/payments/res/components/csc-input.js
Normal file
103
browser/components/payments/res/components/csc-input.js
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import ObservedPropertiesMixin from "../mixins/ObservedPropertiesMixin.js";
|
||||
|
||||
/**
|
||||
* <csc-input placeholder="CVV*"
|
||||
default-value="123"
|
||||
front-tooltip="Look on front of card for CSC"
|
||||
back-tooltip="Look on back of card for CSC"></csc-input>
|
||||
*/
|
||||
|
||||
export default class CscInput extends ObservedPropertiesMixin(HTMLElement) {
|
||||
static get observedAttributes() {
|
||||
return [
|
||||
"back-tooltip",
|
||||
"card-type",
|
||||
"default-value",
|
||||
"disabled",
|
||||
"front-tooltip",
|
||||
"placeholder",
|
||||
"value",
|
||||
];
|
||||
}
|
||||
constructor({
|
||||
useAlwaysVisiblePlaceholder,
|
||||
inputId,
|
||||
} = {}) {
|
||||
super();
|
||||
|
||||
this.useAlwaysVisiblePlaceholder = useAlwaysVisiblePlaceholder;
|
||||
|
||||
this._input = document.createElement("input");
|
||||
this._input.id = inputId || "";
|
||||
this._input.setAttribute("type", "text");
|
||||
this._input.autocomplete = "off";
|
||||
this._input.size = 3;
|
||||
this._input.required = true;
|
||||
// 3 or more digits
|
||||
this._input.pattern = "[0-9]{3,}";
|
||||
this._input.classList.add("security-code");
|
||||
if (useAlwaysVisiblePlaceholder) {
|
||||
this._label = document.createElement("span");
|
||||
this._label.dataset.localization = "cardCVV";
|
||||
this._label.className = "label-text";
|
||||
}
|
||||
this._tooltip = document.createElement("span");
|
||||
this._tooltip.className = "info-tooltip csc";
|
||||
this._tooltip.setAttribute("tabindex", "0");
|
||||
this._tooltip.setAttribute("role", "tooltip");
|
||||
|
||||
// The parent connectedCallback calls its render method before
|
||||
// our connectedCallback can run. This causes issues for parent
|
||||
// code that is looking for all the form elements. Thus, we
|
||||
// append the children during the constructor to make sure they
|
||||
// be part of the DOM sooner.
|
||||
this.appendChild(this._input);
|
||||
if (this.useAlwaysVisiblePlaceholder) {
|
||||
this.appendChild(this._label);
|
||||
}
|
||||
this.appendChild(this._tooltip);
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.render();
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.value) {
|
||||
// Setting the value will trigger form validation
|
||||
// so only set the value if one has been provided.
|
||||
this._input.value = this.value;
|
||||
}
|
||||
if (this.useAlwaysVisiblePlaceholder) {
|
||||
this._label.textContent = this.placeholder || "";
|
||||
} else {
|
||||
this._input.placeholder = this.placeholder || "";
|
||||
}
|
||||
if (this.cardType == "amex") {
|
||||
this._tooltip.setAttribute("aria-label", this.frontTooltip || "");
|
||||
} else {
|
||||
this._tooltip.setAttribute("aria-label", this.backTooltip || "");
|
||||
}
|
||||
}
|
||||
|
||||
get value() {
|
||||
return this._input.value;
|
||||
}
|
||||
|
||||
get isValid() {
|
||||
return this._input.validity.valid;
|
||||
}
|
||||
|
||||
set disabled(value) {
|
||||
// This is kept out of render() since callers
|
||||
// are expecting it to apply immediately.
|
||||
this._input.disabled = value;
|
||||
return !!value;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("csc-input", CscInput);
|
||||
|
|
@ -12,6 +12,11 @@ basic-card-form .editCreditCardForm {
|
|||
"billingAddressGUID billingAddressGUID billingAddressGUID";
|
||||
}
|
||||
|
||||
basic-card-form csc-input {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
basic-card-form .editCreditCardForm > accepted-cards {
|
||||
grid-area: accepted;
|
||||
margin: 0;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
/* import-globals-from ../../../../../browser/extensions/formautofill/content/autofillEditForms.js*/
|
||||
import AcceptedCards from "../components/accepted-cards.js";
|
||||
import CscInput from "../components/csc-input.js";
|
||||
import LabelledCheckbox from "../components/labelled-checkbox.js";
|
||||
import PaymentDialog from "./payment-dialog.js";
|
||||
import PaymentRequestPage from "../components/payment-request-page.js";
|
||||
|
|
@ -36,6 +37,11 @@ export default class BasicCardForm extends PaymentStateSubscriberMixin(PaymentRe
|
|||
this.addressEditLink.href = "javascript:void(0)";
|
||||
this.addressEditLink.addEventListener("click", this);
|
||||
|
||||
this.cscInput = new CscInput({
|
||||
useAlwaysVisiblePlaceholder: true,
|
||||
inputId: "cc-csc",
|
||||
});
|
||||
|
||||
this.persistCheckbox = new LabelledCheckbox();
|
||||
// The persist checkbox shouldn't be part of the record which gets saved so
|
||||
// exclude it from the form.
|
||||
|
|
@ -107,6 +113,11 @@ export default class BasicCardForm extends PaymentStateSubscriberMixin(PaymentRe
|
|||
field.addEventListener("invalid", this);
|
||||
}
|
||||
|
||||
// Replace the form-autofill cc-csc fields with our csc-input.
|
||||
let cscContainer = this.form.querySelector("#cc-csc-container");
|
||||
cscContainer.textContent = "";
|
||||
cscContainer.appendChild(this.cscInput);
|
||||
|
||||
let fragment = document.createDocumentFragment();
|
||||
fragment.append(" ");
|
||||
fragment.append(this.addressEditLink);
|
||||
|
|
@ -148,6 +159,11 @@ export default class BasicCardForm extends PaymentStateSubscriberMixin(PaymentRe
|
|||
} else {
|
||||
this.saveButton.textContent = this.dataset.nextButtonLabel;
|
||||
}
|
||||
|
||||
this.cscInput.placeholder = this.dataset.cscPlaceholder;
|
||||
this.cscInput.frontTooltip = this.dataset.cscFrontInfoTooltip;
|
||||
this.cscInput.backTooltip = this.dataset.cscBackInfoTooltip;
|
||||
|
||||
this.persistCheckbox.label = this.dataset.persistCheckboxLabel;
|
||||
this.persistCheckbox.infoTooltip = this.dataset.persistCheckboxInfoTooltip;
|
||||
this.addressAddLink.textContent = this.dataset.addressAddLinkLabel;
|
||||
|
|
@ -169,7 +185,7 @@ export default class BasicCardForm extends PaymentStateSubscriberMixin(PaymentRe
|
|||
|
||||
// The CVV fields should be hidden and disabled when editing.
|
||||
this.form.querySelector("#cc-csc-container").hidden = editing;
|
||||
this.form.querySelector("#cc-csc").disabled = editing;
|
||||
this.cscInput.disabled = editing;
|
||||
|
||||
// If a card is selected we want to edit it.
|
||||
if (editing) {
|
||||
|
|
@ -258,6 +274,9 @@ export default class BasicCardForm extends PaymentStateSubscriberMixin(PaymentRe
|
|||
}
|
||||
|
||||
onChange(evt) {
|
||||
let ccType = this.form.querySelector("#cc-type");
|
||||
this.cscInput.setAttribute("card-type", ccType.value);
|
||||
|
||||
this.updateSaveButtonState();
|
||||
}
|
||||
|
||||
|
|
@ -429,7 +448,7 @@ export default class BasicCardForm extends PaymentStateSubscriberMixin(PaymentRe
|
|||
id: "payment-summary",
|
||||
},
|
||||
[selectedStateKey]: guid,
|
||||
[selectedStateKey + "SecurityCode"]: this.form.querySelector("#cc-csc").value,
|
||||
[selectedStateKey + "SecurityCode"]: this.cscInput.value,
|
||||
});
|
||||
} catch (ex) {
|
||||
log.warn("saveRecord: error:", ex);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="46" height="27" version="1.1">
|
||||
<defs>
|
||||
<circle id="a" cx="10" cy="10" r="10"/>
|
||||
</defs>
|
||||
<g fill="none" fill-rule="evenodd" stroke="none" stroke-width="1">
|
||||
<path fill="#A1C6FF" d="M37 6.2a10.046 10.046 0 0 0 -2 -0.2c-5.523 0 -10 4.477 -10 10a9.983 9.983 0 0 0 3.999 8h-27.999a1 1 0 0 1 -1 -1v-22a1 1 0 0 1 1 -1h35a1 1 0 0 1 1 1v5.2zm-18 7.8c3.314 0 6 -1.567 6 -3.5s-2.686 -3.5 -6 -3.5 -6 1.567 -6 3.5 2.686 3.5 6 3.5z"/>
|
||||
<path fill="#5F5F5F" d="M2 17h9v2h-9v-2zm0 -15h33v3h-33v-3zm0 18h15v2h-15v-2zm10 -3h13v2h-13v-2z"/>
|
||||
<g transform="translate(25 6)">
|
||||
<mask id="b" fill="#fff">
|
||||
<use xlink:href="#a"/>
|
||||
</mask>
|
||||
<use stroke="#FFF" stroke-width="1.5" xlink:href="#a"/>
|
||||
<g mask="url(#b)">
|
||||
<g transform="translate(-77 -31)">
|
||||
<rect width="99.39" height="69.141" x="0" y="0" fill="#A1C6FF" fill-rule="evenodd" rx="1"/>
|
||||
<path fill="#5F5F5F" fill-rule="evenodd" d="M79 46h17v6h-17z"/>
|
||||
<text fill="none" font-family="sans-serif" font-size="6">
|
||||
<tspan x="80" y="42" fill="#5F5F5F">1234</tspan>
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
|
|
@ -0,0 +1,25 @@
|
|||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="45" height="27" version="1.1">
|
||||
<defs>
|
||||
<circle id="a" cx="10" cy="10" r="10"/>
|
||||
</defs>
|
||||
<g fill="none" fill-rule="evenodd" stroke="none" stroke-width="1">
|
||||
<path fill="#62A0FF" d="M37 6.458a9.996 9.996 0 0 0 -3 -0.458c-3.701 0 -6.933 2.011 -8.662 5h-22.338v5h21a9.983 9.983 0 0 0 3.999 8h-26.999a1 1 0 0 1 -1 -1v-22a1 1 0 0 1 1 -1h35a1 1 0 0 1 1 1v5.458z"/>
|
||||
<path fill="#5F5F5F" d="M37 6.458a9.996 9.996 0 0 0 -3 -0.458 9.97 9.97 0 0 0 -7.141 3h-26.859v-6h37v3.458z"/>
|
||||
<g transform="translate(24 6)">
|
||||
<mask id="b" fill="#fff">
|
||||
<use xlink:href="#a"/>
|
||||
</mask>
|
||||
<use stroke="#FFF" stroke-width="1.5" xlink:href="#a"/>
|
||||
<g mask="url(#b)">
|
||||
<path fill="#62A0FF" fill-rule="evenodd" d="M-41.923 -15.615h64.476a1 1 0 0 1 1 1v44.244a1 1 0 0 1 -1 1h-64.476a1 1 0 0 1 -1 -1v-44.244a1 1 0 0 1 1 -1zm2.923 19.615v9h55v-9h-55z"/>
|
||||
<path fill="#5F5F5F" fill-rule="evenodd" d="M-43 -10h66v12h-66z"/>
|
||||
<text fill="none" font-family="sans-serif" font-size="6" transform="translate(-43.923 -15.615)">
|
||||
<tspan x="47.676" y="26.104" fill="#5F5F5F">123</tspan>
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
|
@ -264,7 +264,7 @@ export default class PaymentDialog extends PaymentStateSubscriberMixin(HTMLEleme
|
|||
(this._isPayerRequested(state.request.paymentOptions) &&
|
||||
(!this._payerAddressPicker.selectedOption ||
|
||||
this._payerAddressPicker.classList.contains(INVALID_CLASS_NAME))) ||
|
||||
!this._paymentMethodPicker.securityCodeInput.validity.valid ||
|
||||
!this._paymentMethodPicker.securityCodeInput.isValid ||
|
||||
!this._paymentMethodPicker.selectedOption ||
|
||||
this._paymentMethodPicker.classList.contains(INVALID_CLASS_NAME) ||
|
||||
state.changesPrevented;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import BasicCardOption from "../components/basic-card-option.js";
|
||||
import CscInput from "../components/csc-input.js";
|
||||
import RichPicker from "./rich-picker.js";
|
||||
import paymentRequest from "../paymentRequest.js";
|
||||
/* import-globals-from ../unprivileged-fallbacks.js */
|
||||
|
|
@ -17,14 +18,11 @@ export default class PaymentMethodPicker extends RichPicker {
|
|||
constructor() {
|
||||
super();
|
||||
this.dropdown.setAttribute("option-type", "basic-card-option");
|
||||
this.securityCodeInput = document.createElement("input");
|
||||
this.securityCodeInput.autocomplete = "off";
|
||||
this.securityCodeInput.placeholder = this.dataset.cvvPlaceholder;
|
||||
this.securityCodeInput.size = 3;
|
||||
this.securityCodeInput.required = true;
|
||||
// 3 or more digits
|
||||
this.securityCodeInput.pattern = "[0-9]{3,}";
|
||||
this.securityCodeInput.classList.add("security-code");
|
||||
this.securityCodeInput = new CscInput();
|
||||
this.securityCodeInput.className = "security-code-container";
|
||||
this.securityCodeInput.placeholder = this.dataset.cscPlaceholder;
|
||||
this.securityCodeInput.backTooltip = this.dataset.cscBackTooltip;
|
||||
this.securityCodeInput.frontTooltip = this.dataset.cscFrontTooltip;
|
||||
this.securityCodeInput.addEventListener("change", this);
|
||||
this.securityCodeInput.addEventListener("input", this);
|
||||
}
|
||||
|
|
@ -81,6 +79,10 @@ export default class PaymentMethodPicker extends RichPicker {
|
|||
this.securityCodeInput.defaultValue = securityCodeState;
|
||||
}
|
||||
|
||||
let selectedCardType = (basicCards[selectedPaymentCardGUID] &&
|
||||
basicCards[selectedPaymentCardGUID]["cc-type"]) || "";
|
||||
this.securityCodeInput.cardType = selectedCardType;
|
||||
|
||||
super.render(state);
|
||||
}
|
||||
|
||||
|
|
@ -123,7 +125,7 @@ export default class PaymentMethodPicker extends RichPicker {
|
|||
}
|
||||
}
|
||||
|
||||
onInputOrChange({target}) {
|
||||
onInputOrChange({currentTarget}) {
|
||||
let selectedKey = this.selectedStateKey;
|
||||
let stateChange = {};
|
||||
|
||||
|
|
@ -131,8 +133,8 @@ export default class PaymentMethodPicker extends RichPicker {
|
|||
return;
|
||||
}
|
||||
|
||||
switch (target) {
|
||||
case this.dropdown.popupBox: {
|
||||
switch (currentTarget) {
|
||||
case this.dropdown: {
|
||||
stateChange[selectedKey] = this.dropdown.value;
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,16 +55,23 @@ payment-method-picker.rich-picker {
|
|||
grid-template-columns: 20fr 1fr auto auto;
|
||||
grid-template-areas:
|
||||
"label spacer edit add"
|
||||
"dropdown cvv cvv cvv"
|
||||
"dropdown csc csc csc"
|
||||
"invalid invalid invalid invalid";
|
||||
}
|
||||
|
||||
payment-method-picker > input {
|
||||
border: 1px solid #0C0C0D33;
|
||||
border-inline-start: none;
|
||||
grid-area: cvv;
|
||||
.security-code-container {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
grid-area: csc;
|
||||
margin: 10px 0; /* Has to be same as rich-select */
|
||||
padding: 8px;
|
||||
/* So the error outline appears above the adjacent dropdown */
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.rich-picker .security-code {
|
||||
border: 1px solid #0C0C0D33;
|
||||
/* Override the border from common.css */
|
||||
border-inline-start: none !important;
|
||||
flex-grow: 1;
|
||||
padding: 8px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -365,6 +365,25 @@ let BASIC_CARDS_1 = {
|
|||
"cc-family-name": "Fields",
|
||||
"cc-type": "discover",
|
||||
},
|
||||
"amex-card": {
|
||||
methodName: "basic-card",
|
||||
billingAddressGUID: "68gjdh354j",
|
||||
"cc-number": "************1941",
|
||||
"guid": "amex-card",
|
||||
"version": 1,
|
||||
"timeCreated": 1517890536491,
|
||||
"timeLastModified": 1517890564518,
|
||||
"timeLastUsed": 0,
|
||||
"timesUsed": 0,
|
||||
"cc-name": "Capt America",
|
||||
"cc-given-name": "Capt",
|
||||
"cc-additional-name": "",
|
||||
"cc-family-name": "America",
|
||||
"cc-type": "amex",
|
||||
"cc-exp-month": 6,
|
||||
"cc-exp-year": 2023,
|
||||
"cc-exp": "2023-06",
|
||||
},
|
||||
"missing-cc-name": {
|
||||
methodName: "basic-card",
|
||||
"cc-number": "************8563",
|
||||
|
|
|
|||
|
|
@ -210,12 +210,14 @@ payment-dialog[changes-prevented][complete-status="success"] #pay {
|
|||
content: attr(aria-label);
|
||||
display: block;
|
||||
position: absolute;
|
||||
padding: 2px 5px;
|
||||
padding: 3px 5px;
|
||||
background-color: #fff;
|
||||
border: 1px solid #bebebf;
|
||||
box-shadow: 1px 1px 3px #bebebf;
|
||||
font-size: smaller;
|
||||
min-width: 188px;
|
||||
line-height: normal;
|
||||
width: 188px;
|
||||
/* Center the tooltip over the (i) icon (188px / 2 - 5px (padding) - 1px (border)). */
|
||||
left: -86px;
|
||||
bottom: 20px;
|
||||
}
|
||||
|
|
@ -226,6 +228,28 @@ payment-dialog[changes-prevented][complete-status="success"] #pay {
|
|||
right: -86px;
|
||||
}
|
||||
|
||||
.csc.info-tooltip:focus::after,
|
||||
.csc.info-tooltip:hover::after {
|
||||
/* Right-align the tooltip over the (i) icon (-188px - 60px (padding) - 2px (border) + 4px ((i) start padding) + 16px ((i) icon width)). */
|
||||
left: -226px;
|
||||
background-position: top 5px left 5px;
|
||||
background-image: url(./containers/cvv-hint-image-back.svg);
|
||||
background-repeat: no-repeat;
|
||||
padding-inline-start: 55px;
|
||||
}
|
||||
|
||||
.csc.info-tooltip[cc-type="amex"]::after {
|
||||
background-image: url(./containers/cvv-hint-image-front.svg);
|
||||
}
|
||||
|
||||
.csc.info-tooltip:dir(rtl):focus::after,
|
||||
.csc.info-tooltip:dir(rtl):hover::after {
|
||||
left: auto;
|
||||
/* Left-align the tooltip over the (i) icon (-188px - 60px (padding) - 2px (border) + 4px ((i) start padding) + 16px ((i) icon width)). */
|
||||
right: -226px;
|
||||
background-position: top 5px right 5px;
|
||||
}
|
||||
|
||||
.branding {
|
||||
background-image: url(chrome://branding/content/icon32.png);
|
||||
background-size: 16px;
|
||||
|
|
|
|||
|
|
@ -40,7 +40,9 @@
|
|||
<!ENTITY billingAddress.editPage.title "Edit Billing Address">
|
||||
<!ENTITY basicCard.addPage.title "Add Credit Card">
|
||||
<!ENTITY basicCard.editPage.title "Edit Credit Card">
|
||||
<!ENTITY basicCard.cvv.placeholder "CVV&fieldRequiredSymbol;">
|
||||
<!ENTITY basicCard.csc.placeholder "CVV">
|
||||
<!ENTITY basicCard.csc.back.infoTooltip "3 digit number found on the back of your credit card.">
|
||||
<!ENTITY basicCard.csc.front.infoTooltip "3 digit number found on the front of your credit card.">
|
||||
<!ENTITY payer.addPage.title "Add Payer Contact">
|
||||
<!ENTITY payer.editPage.title "Edit Payer Contact">
|
||||
<!ENTITY payerLabel "Contact Information">
|
||||
|
|
@ -150,7 +152,9 @@
|
|||
<payment-method-picker selected-state-key="selectedPaymentCard"
|
||||
data-add-link-label="&basicCard.addLink.label;"
|
||||
data-edit-link-label="&basicCard.editLink.label;"
|
||||
data-cvv-placeholder="&basicCard.cvv.placeholder;"
|
||||
data-csc-placeholder="&basicCard.csc.placeholder;"
|
||||
data-csc-back-tooltip="&basicCard.csc.back.infoTooltip;"
|
||||
data-csc-front-tooltip="&basicCard.csc.front.infoTooltip;"
|
||||
data-invalid-label="&invalidOption.label;"
|
||||
label="&paymentMethodsLabel;">
|
||||
</payment-method-picker>
|
||||
|
|
@ -199,6 +203,9 @@
|
|||
data-cancel-button-label="&cancelPaymentButton.label;"
|
||||
data-persist-checkbox-label="&basicCardPage.persistCheckbox.label;"
|
||||
data-persist-checkbox-info-tooltip="&basicCardPage.persistCheckbox.infoTooltip;"
|
||||
data-csc-placeholder="&basicCard.csc.placeholder;"
|
||||
data-csc-back-info-tooltip="&basicCard.csc.back.infoTooltip;"
|
||||
data-csc-front-info-tooltip="&basicCard.csc.front.infoTooltip;"
|
||||
data-accepted-cards-label="&acceptedCards.label;"
|
||||
data-field-required-symbol="&fieldRequiredSymbol;"
|
||||
hidden="hidden"></basic-card-form>
|
||||
|
|
|
|||
|
|
@ -293,7 +293,7 @@ var PaymentTestUtils = {
|
|||
let picker = Cu.waiveXrays(content.document.querySelector("payment-method-picker"));
|
||||
// Unwaive to access the ChromeOnly `setUserInput` API.
|
||||
// setUserInput dispatches changes events.
|
||||
Cu.unwaiveXrays(picker.securityCodeInput).setUserInput(securityCode);
|
||||
Cu.unwaiveXrays(picker.securityCodeInput).querySelector("input").setUserInput(securityCode);
|
||||
},
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ add_task(async function test_saveButton() {
|
|||
let year = (new Date()).getFullYear().toString();
|
||||
fillField(form.form.querySelector("#cc-exp-year"), year);
|
||||
fillField(form.form.querySelector("#cc-type"), "visa");
|
||||
fillField(form.form.querySelector("#cc-csc"), "123");
|
||||
fillField(form.form.querySelector("csc-input input"), "123");
|
||||
isnot(form.form.querySelector("#billingAddressGUID").value, address2.guid,
|
||||
"Check initial billing address");
|
||||
fillField(form.form.querySelector("#billingAddressGUID"), address2.guid);
|
||||
|
|
@ -222,7 +222,8 @@ add_task(async function test_requiredAttributePropagated() {
|
|||
continue;
|
||||
}
|
||||
let container = element.closest("label") || element.closest("div");
|
||||
ok(container.hasAttribute("required"), "Container should also be marked as required");
|
||||
ok(container.hasAttribute("required"),
|
||||
`Container ${container.id} should also be marked as required`);
|
||||
}
|
||||
// Now test that toggling the `required` attribute will affect the container.
|
||||
let sampleRequiredElement = requiredElements[0];
|
||||
|
|
@ -460,7 +461,7 @@ add_task(async function test_field_validity_updates() {
|
|||
let ccNumber = form.form.querySelector("#cc-number");
|
||||
let nameInput = form.form.querySelector("#cc-name");
|
||||
let typeInput = form.form.querySelector("#cc-type");
|
||||
let cscInput = form.form.querySelector("#cc-csc");
|
||||
let cscInput = form.form.querySelector("csc-input input");
|
||||
let monthInput = form.form.querySelector("#cc-exp-month");
|
||||
let yearInput = form.form.querySelector("#cc-exp-year");
|
||||
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ async function setup({shippingRequired, payerRequired}) {
|
|||
|
||||
// Fill the security code input so it doesn't interfere with checking the pay
|
||||
// button state for dropdown changes.
|
||||
el1._paymentMethodPicker.securityCodeInput.select();
|
||||
el1._paymentMethodPicker.securityCodeInput.querySelector("input").select();
|
||||
sendString("123");
|
||||
await asyncElementRendered();
|
||||
}
|
||||
|
|
@ -234,14 +234,14 @@ add_task(async function test_securityCodeRequired() {
|
|||
selectFirstItemOfPicker(picker);
|
||||
await stateChangedPromise;
|
||||
|
||||
picker.securityCodeInput.select();
|
||||
picker.securityCodeInput.querySelector("input").select();
|
||||
stateChangedPromise = promiseStateChange(el1.requestStore);
|
||||
synthesizeKey("VK_DELETE");
|
||||
await stateChangedPromise;
|
||||
|
||||
ok(payButton.disabled, "Button is disabled when CVV is empty");
|
||||
|
||||
picker.securityCodeInput.select();
|
||||
picker.securityCodeInput.querySelector("input").select();
|
||||
stateChangedPromise = promiseStateChange(el1.requestStore);
|
||||
sendString("123");
|
||||
await stateChangedPromise;
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ add_task(async function test_change_selected_card() {
|
|||
let stateChangePromise = promiseStateChange(picker1.requestStore);
|
||||
|
||||
// Type in the security code field
|
||||
picker1.securityCodeInput.focus();
|
||||
picker1.securityCodeInput.querySelector("input").focus();
|
||||
sendString("836");
|
||||
sendKey("Tab");
|
||||
let state = await stateChangePromise;
|
||||
|
|
|
|||
|
|
@ -61,15 +61,7 @@
|
|||
<span data-localization="cardNetwork" class="label-text"/>
|
||||
</label>
|
||||
<label id="cc-csc-container" class="container" hidden="hidden">
|
||||
<!-- Keep these attributes in-sync with securityCodeInput in payment-method-picker.js -->
|
||||
<input id="cc-csc"
|
||||
type="text"
|
||||
autocomplete="off"
|
||||
size="3"
|
||||
required="required"
|
||||
pattern="[0-9]{3,}"
|
||||
disabled="disabled"/>
|
||||
<span data-localization="cardCVV" class="label-text"/>
|
||||
<!-- The CSC container will get filled in by forms that need a CSC (using csc-input.js) -->
|
||||
</label>
|
||||
<div id="billingAddressGUID-container" class="billingAddressRow container rich-picker">
|
||||
<select id="billingAddressGUID" required="required">
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ form div {
|
|||
line-height: 1em;
|
||||
}
|
||||
|
||||
form :-moz-any(label, div) > .label-text {
|
||||
form :-moz-any(label, div) .label-text {
|
||||
position: absolute;
|
||||
color: GrayText;
|
||||
pointer-events: none;
|
||||
|
|
@ -49,8 +49,8 @@ form :-moz-any(label, div) > .label-text {
|
|||
font-size .2s var(--animation-easing-function);
|
||||
}
|
||||
|
||||
form :-moz-any(label, div):focus-within > .label-text,
|
||||
form :-moz-any(label, div) > .label-text[field-populated] {
|
||||
form :-moz-any(label, div):focus-within .label-text,
|
||||
form :-moz-any(label, div) .label-text[field-populated] {
|
||||
top: 0;
|
||||
font-size: var(--in-field-label-size);
|
||||
}
|
||||
|
|
@ -65,8 +65,8 @@ form :-moz-any(input, select, textarea):focus:-moz-ui-invalid ~ .label-text {
|
|||
color: var(--in-content-text-color);
|
||||
}
|
||||
|
||||
form div[required] > label > .label-text::after,
|
||||
form :-moz-any(label, div)[required] > .label-text::after {
|
||||
form div[required] > label .label-text::after,
|
||||
form :-moz-any(label, div)[required] .label-text::after {
|
||||
content: attr(fieldRequiredSymbol);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue