@internetarchive/donation-form 0.5.17-a1 → 0.5.17-a3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/form-elements/contact-form/contact-form.js +8 -4
- package/dist/src/form-elements/contact-form/contact-form.js.map +1 -1
- package/dist/test/tests/donation-form-controller.test.js +11 -0
- package/dist/test/tests/donation-form-controller.test.js.map +1 -1
- package/package.json +1 -1
- package/src/form-elements/contact-form/contact-form.ts +6 -2
|
@@ -149,17 +149,21 @@ let ContactForm = class ContactForm extends LitElement {
|
|
|
149
149
|
<badged-input>
|
|
150
150
|
<select id="donation-contact-form-countryCodeAlpha2"
|
|
151
151
|
@change=${(e) => {
|
|
152
|
-
var _a, _b, _c, _d, _e, _f;
|
|
152
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
153
153
|
const currCountry = this.selectedCountry;
|
|
154
154
|
this.selectedCountry = ((_a = e.target) === null || _a === void 0 ? void 0 : _a.value) ? (_b = e.target) === null || _b === void 0 ? void 0 : _b.value : currCountry;
|
|
155
|
-
// update required visual cue on postal code
|
|
155
|
+
// update required visual cue on region/state/province & postal code fields
|
|
156
156
|
if (this.selectedCountry === 'US') {
|
|
157
157
|
(_c = this.postalBadgedInput) === null || _c === void 0 ? void 0 : _c.setAttribute('required', '');
|
|
158
158
|
(_d = this.postalCodeField) === null || _d === void 0 ? void 0 : _d.setAttribute('required', '');
|
|
159
|
+
(_e = this.regionBadgedInput) === null || _e === void 0 ? void 0 : _e.setAttribute('required', '');
|
|
160
|
+
(_f = this.regionField) === null || _f === void 0 ? void 0 : _f.setAttribute('required', '');
|
|
159
161
|
}
|
|
160
162
|
else {
|
|
161
|
-
(
|
|
162
|
-
(
|
|
163
|
+
(_g = this.postalBadgedInput) === null || _g === void 0 ? void 0 : _g.removeAttribute('required');
|
|
164
|
+
(_h = this.postalCodeField) === null || _h === void 0 ? void 0 : _h.removeAttribute('required');
|
|
165
|
+
(_j = this.regionBadgedInput) === null || _j === void 0 ? void 0 : _j.removeAttribute('required');
|
|
166
|
+
(_k = this.regionField) === null || _k === void 0 ? void 0 : _k.removeAttribute('required');
|
|
163
167
|
}
|
|
164
168
|
}}>
|
|
165
169
|
${Object.keys(countries).map(key => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contact-form.js","sourceRoot":"","sources":["../../../../src/form-elements/contact-form/contact-form.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, html, css, TemplateResult } from 'lit';\nimport { customElement, property, query } from 'lit/decorators.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\n\nimport {\n BillingInfo,\n CustomerInfo,\n DonorContactInfo,\n} from '@internetarchive/donation-form-data-models';\nimport { AutoCompleteFieldOptions } from './autocomplete-field-options';\nimport { SpacerOption } from '../badged-input';\nimport { BadgedInput } from '../badged-input';\nimport '../badged-input';\n\nimport emailImg from '@internetarchive/icon-email';\nimport localePinImg from '@internetarchive/icon-locale-pin';\nimport userIcon from '@internetarchive/icon-user';\n\nimport { countries } from './countries';\n\n@customElement('contact-form')\nexport class ContactForm extends LitElement {\n @query('badged-input.donation-contact-form-email') emailBadgedInput!: BadgedInput;\n @query('#donation-contact-form-email') emailField!: HTMLInputElement;\n\n @query('badged-input.donation-contact-form-first-name') firstNameBadgedInput!: BadgedInput;\n @query('#donation-contact-form-first-name') firstNameField!: HTMLInputElement;\n\n @query('badged-input.donation-contact-form-last-name') lastNameBadgedInput!: BadgedInput;\n @query('#donation-contact-form-last-name') lastNameField!: HTMLInputElement;\n\n @query('badged-input.donation-contact-form-postal-code') postalBadgedInput!: BadgedInput;\n @query('#donation-contact-form-postal-code') postalCodeField!: HTMLInputElement;\n\n @query('badged-input.donation-contact-form-street-address')\n streetAddressBadgedInput!: BadgedInput;\n @query('#donation-contact-form-street-address') streetAddressField!: HTMLInputElement;\n\n @query('badged-input.donation-contact-form-extended-address')\n extendedAddressBadgedInput!: BadgedInput;\n @query('#donation-contact-form-extended-address') extendedAddressField!: HTMLInputElement;\n\n @query('badged-input.donation-contact-form-locality') localityBadgedInput!: BadgedInput;\n @query('#donation-contact-form-locality') localityField!: HTMLInputElement;\n\n @query('badged-input.donation-contact-form-region') regionBadgedInput!: BadgedInput;\n @query('#donation-contact-form-region') regionField!: HTMLInputElement;\n\n @query('#donation-contact-form-countryCodeAlpha2') countryCodeAlpha2Field!: HTMLSelectElement;\n\n @query('#donation-contact-form-error-message') errorMessage!: HTMLDivElement;\n @query('form') form!: HTMLFormElement;\n\n /** @keyof countries */\n @property({ type: String }) selectedCountry: string = 'US';\n\n reportValidity(): boolean {\n const fieldBadgedInputs: Array<[HTMLInputElement, BadgedInput]> = [\n [this.emailField, this.emailBadgedInput],\n [this.firstNameField, this.firstNameBadgedInput],\n [this.lastNameField, this.lastNameBadgedInput],\n [this.regionField, this.regionBadgedInput],\n [this.localityField, this.localityBadgedInput],\n [this.streetAddressField, this.streetAddressBadgedInput],\n [this.postalCodeField, this.postalBadgedInput],\n ];\n\n let isValid = true;\n fieldBadgedInputs.forEach(([inputElement, badgedInput]) => {\n const fieldValid = inputElement.checkValidity();\n isValid = isValid && fieldValid;\n if (!fieldValid) {\n badgedInput.error = true;\n }\n });\n\n if (!isValid) {\n this.errorMessage.innerText = 'Please enter any missing contact information below';\n } else {\n this.errorMessage.innerText = '';\n }\n\n return isValid;\n }\n\n focus(): void {\n this.emailField.focus();\n }\n\n /** @inheritdoc */\n render(): TemplateResult {\n return html`\n <div id=\"donation-contact-form-error-message\"></div>\n <form>\n <fieldset>\n <div class=\"row\">\n ${this.generateInput({\n id: 'donation-contact-form-email',\n placeholder: 'Email',\n required: true,\n fieldType: 'email',\n name: 'email',\n autocomplete: 'email',\n maxlength: 255,\n icon: emailImg,\n })}\n </div>\n </fieldset>\n\n <fieldset>\n <div class=\"row\">\n ${this.generateInput({\n id: 'donation-contact-form-first-name',\n placeholder: 'First name',\n name: 'fname',\n required: true,\n maxlength: 255,\n autocomplete: 'given-name',\n icon: userIcon,\n })}\n </div>\n <div class=\"row\">\n ${this.generateInput({\n id: 'donation-contact-form-last-name',\n placeholder: 'Last name',\n name: 'lname',\n autocomplete: 'family-name',\n required: true,\n maxlength: 255,\n })}\n </div>\n </fieldset>\n <fieldset>\n <div class=\"row\">\n ${this.generateInput({\n id: 'donation-contact-form-street-address',\n placeholder: 'Address Line 1',\n required: true,\n autocomplete: 'address-line1',\n icon: localePinImg,\n name: 'street-address',\n })}\n </div>\n <div class=\"row\">\n ${this.generateInput({\n id: 'donation-contact-form-extended-address',\n placeholder: 'Address Line 2 (optional)',\n autocomplete: 'address-line2',\n required: false,\n name: 'extended-address',\n })}\n </div>\n <div class=\"row\">\n ${this.generateInput({\n id: 'donation-contact-form-locality',\n placeholder: 'City',\n autocomplete: 'address-level2',\n required: true,\n name: 'locality',\n })}\n </div>\n <div class=\"row\">\n ${this.generateInput({\n id: 'donation-contact-form-region',\n placeholder: 'State / Province',\n autocomplete: 'address-level1',\n required: true,\n name: 'region',\n })}\n ${this.generateInput({\n id: 'donation-contact-form-postal-code',\n placeholder: 'Zip / Postal',\n autocomplete: 'postal-code',\n required: true,\n name: 'postal',\n maxlength: 9,\n // must start with a character, then may contain spaces\n validationPattern: '[a-zA-Z\\\\-\\\\d]+[a-zA-Z\\\\-\\\\d\\\\s]*',\n iconSpaceOption: SpacerOption.CompressSpace,\n })}\n </div>\n <div class=\"row\">\n ${this.countrySelectorTemplate}\n </div>\n </fieldset>\n </form>\n ${this.getStyles}\n `;\n }\n\n private get countrySelectorTemplate(): TemplateResult {\n return html`\n <badged-input>\n <select id=\"donation-contact-form-countryCodeAlpha2\"\n @change=${(e: Event) => {\n const currCountry = this.selectedCountry;\n this.selectedCountry = (e.target as HTMLInputElement)?.value ? (e.target as HTMLInputElement)?.value as string : currCountry;\n // update required visual cue on postal code\n if (this.selectedCountry === 'US') {\n this.postalBadgedInput?.setAttribute('required', '');\n this.postalCodeField?.setAttribute('required', '');\n } else {\n this.postalBadgedInput?.removeAttribute('required');\n this.postalCodeField?.removeAttribute('required');\n }\n }}>\n ${Object.keys(countries).map(key => {\n const name = countries[key];\n return html`\n <option value=${key} ?selected=${key === this.selectedCountry}>${name}</option>\n `;\n })}\n </select>\n </badged-input>\n `;\n }\n\n /** @inheritdoc */\n createRenderRoot(): this {\n // Render template without shadow DOM. Note that shadow DOM features like\n // encapsulated CSS and slots are unavailable.\n // Form autofill does not work properly in the shadow DOM\n // so we need our form fields in the light DOM\n return this;\n }\n\n // reset the error state when the user focuses the input\n private inputFocused(e: KeyboardEvent): void {\n this.errorMessage.innerText = '';\n const input = e.target as HTMLInputElement;\n const inputIdentifier = input.id;\n const badgedInput = this.querySelector(`badged-input.${inputIdentifier}`) as BadgedInput;\n badgedInput.error = false;\n }\n\n private generateInput(options: {\n id: string;\n placeholder: string;\n required?: boolean;\n fieldType?: 'text' | 'email';\n autocomplete?: AutoCompleteFieldOptions;\n maxlength?: number;\n name: string;\n icon?: TemplateResult;\n iconSpaceOption?: SpacerOption;\n validationPattern?: string;\n }): TemplateResult {\n const required = options.required ?? true;\n const fieldType = options.fieldType ?? 'text';\n const iconOption = options.iconSpaceOption ?? SpacerOption.LeaveSpace;\n\n return html`\n <badged-input\n class=${options.id}\n .icon=${options.icon}\n .iconSpaceOption=${iconOption}\n ?required=${options.required}\n >\n <label for=${options.id}>${options.placeholder}</label>\n <input\n type=${fieldType}\n id=${options.id}\n class=\"donation-contact-form-input\"\n name=${options.name}\n aria-label=${options.placeholder}\n placeholder=${options.placeholder}\n maxlength=${ifDefined(options.maxlength)}\n autocomplete=${options.autocomplete ?? 'on'}\n pattern=${ifDefined(options.validationPattern)}\n @focus=${this.inputFocused}\n ?required=${required}\n />\n </badged-input>\n `;\n }\n\n get donorContactInfo(): DonorContactInfo {\n return new DonorContactInfo({\n billing: this.billingInfo,\n customer: this.contactInfo,\n });\n }\n\n get billingInfo(): BillingInfo {\n const billingInfo = new BillingInfo({\n streetAddress: this.streetAddressField.value,\n extendedAddress: this.extendedAddressField.value,\n locality: this.localityField.value,\n region: this.regionField.value,\n postalCode: this.postalCodeField.value,\n countryCodeAlpha2: this.countryCodeAlpha2Field.value,\n });\n return billingInfo;\n }\n\n get contactInfo(): CustomerInfo {\n return new CustomerInfo({\n email: this.emailField.value,\n firstName: this.firstNameField.value,\n lastName: this.lastNameField.value,\n });\n }\n\n /**\n * This is not the normal LitElement styles block.\n *\n * This element uses the clear DOM instead of the shadow DOM so it can't use\n * the shadowRoot's isolated styling. This is a bit of a workaround to keep all of\n * the styling local by writing out our own <style> tag and just be careful about\n * the selectors since they will leak outside of this component.\n *\n * @readonly\n * @private\n * @type {TemplateResult}\n * @memberof ContactForm\n */\n private get getStyles(): TemplateResult {\n const noIconSpacerWidth = css`var(--badgedInputNoIconSpacerWidth, 3rem)`;\n const iconSpacerWidth = css`var(--badgedInputIconSpacerWidth, 5rem)`;\n\n const fieldSetSpacing = css`var(--fieldSetSpacing, 1rem)`;\n const fieldFontFamily = css`var(--fontFamily, \"Helvetica Neue\", Helvetica, Arial, sans-serif)`;\n const fieldFontSize = css`var(--contactFieldFontSize, 1.6rem)`;\n const fieldFontColor = css`var(--inputFieldFontColor, #333)`;\n\n const iconFieldWidth = css`calc(100% - ${iconSpacerWidth})`;\n const noIconFieldWidth = css`calc(100% - ${noIconSpacerWidth})`;\n\n return html`\n <style>\n /*\n **NOTE**\n This element is in the lightDOM so be sure to prefix all styles\n with \"contact-form\" so styles don't leak.\n */\n contact-form fieldset {\n border: 0;\n padding: 0;\n margin: 0;\n margin-bottom: ${fieldSetSpacing};\n background-color: white;\n }\n\n /* These 1px and 0 margins in the next few selectors are to account for the\n double outlines caused by the fields being right next to each other */\n contact-form .row {\n display: flex;\n margin: -1px 0 0 0;\n }\n\n contact-form fieldset .row:first-child {\n margin-top: 0;\n }\n\n contact-form badged-input.donation-contact-form-region {\n width: 60%;\n }\n\n contact-form badged-input.donation-contact-form-postal-code {\n width: 40%;\n }\n\n contact-form #donation-contact-form-region {\n width: ${iconFieldWidth};\n }\n\n contact-form #donation-contact-form-postal-code {\n width: ${noIconFieldWidth};\n }\n\n contact-form #donation-contact-form-error-message {\n color: red;\n font-size: 1.4rem;\n margin-bottom: 0.6rem;\n }\n\n contact-form #donation-contact-form-last-name {\n width: ${noIconFieldWidth};\n }\n\n /* only show for screen readers */\n contact-form label {\n position: absolute;\n left: -10000px;\n top: auto;\n width: 1px;\n height: 1px;\n overflow: hidden;\n }\n\n contact-form .donation-contact-form-input {\n width: ${iconFieldWidth};\n border: 0;\n outline: 0;\n background: transparent;\n font-weight: bold;\n color: ${fieldFontColor};\n font-size: ${fieldFontSize};\n padding: 0;\n font-family: ${fieldFontFamily};\n }\n\n contact-form .donation-contact-form-input::placeholder {\n color: revert;\n }\n\n contact-form #donation-contact-form-countryCodeAlpha2 {\n width: ${iconFieldWidth};\n height: 100%;\n box-sizing: border-box;\n font-weight: bold;\n font-size: ${fieldFontSize};\n font-family: ${fieldFontFamily};\n border: 0;\n background: #fff;\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n }\n </style>\n `;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"contact-form.js","sourceRoot":"","sources":["../../../../src/form-elements/contact-form/contact-form.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, html, css, TemplateResult } from 'lit';\nimport { customElement, property, query } from 'lit/decorators.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\n\nimport {\n BillingInfo,\n CustomerInfo,\n DonorContactInfo,\n} from '@internetarchive/donation-form-data-models';\nimport { AutoCompleteFieldOptions } from './autocomplete-field-options';\nimport { SpacerOption } from '../badged-input';\nimport { BadgedInput } from '../badged-input';\nimport '../badged-input';\n\nimport emailImg from '@internetarchive/icon-email';\nimport localePinImg from '@internetarchive/icon-locale-pin';\nimport userIcon from '@internetarchive/icon-user';\n\nimport { countries } from './countries';\n\n@customElement('contact-form')\nexport class ContactForm extends LitElement {\n @query('badged-input.donation-contact-form-email') emailBadgedInput!: BadgedInput;\n @query('#donation-contact-form-email') emailField!: HTMLInputElement;\n\n @query('badged-input.donation-contact-form-first-name') firstNameBadgedInput!: BadgedInput;\n @query('#donation-contact-form-first-name') firstNameField!: HTMLInputElement;\n\n @query('badged-input.donation-contact-form-last-name') lastNameBadgedInput!: BadgedInput;\n @query('#donation-contact-form-last-name') lastNameField!: HTMLInputElement;\n\n @query('badged-input.donation-contact-form-postal-code') postalBadgedInput!: BadgedInput;\n @query('#donation-contact-form-postal-code') postalCodeField!: HTMLInputElement;\n\n @query('badged-input.donation-contact-form-street-address')\n streetAddressBadgedInput!: BadgedInput;\n @query('#donation-contact-form-street-address') streetAddressField!: HTMLInputElement;\n\n @query('badged-input.donation-contact-form-extended-address')\n extendedAddressBadgedInput!: BadgedInput;\n @query('#donation-contact-form-extended-address') extendedAddressField!: HTMLInputElement;\n\n @query('badged-input.donation-contact-form-locality') localityBadgedInput!: BadgedInput;\n @query('#donation-contact-form-locality') localityField!: HTMLInputElement;\n\n @query('badged-input.donation-contact-form-region') regionBadgedInput!: BadgedInput;\n @query('#donation-contact-form-region') regionField!: HTMLInputElement;\n\n @query('#donation-contact-form-countryCodeAlpha2') countryCodeAlpha2Field!: HTMLSelectElement;\n\n @query('#donation-contact-form-error-message') errorMessage!: HTMLDivElement;\n @query('form') form!: HTMLFormElement;\n\n /** @keyof countries */\n @property({ type: String }) selectedCountry = 'US';\n\n reportValidity(): boolean {\n const fieldBadgedInputs: Array<[HTMLInputElement, BadgedInput]> = [\n [this.emailField, this.emailBadgedInput],\n [this.firstNameField, this.firstNameBadgedInput],\n [this.lastNameField, this.lastNameBadgedInput],\n [this.regionField, this.regionBadgedInput],\n [this.localityField, this.localityBadgedInput],\n [this.streetAddressField, this.streetAddressBadgedInput],\n [this.postalCodeField, this.postalBadgedInput],\n ];\n\n let isValid = true;\n fieldBadgedInputs.forEach(([inputElement, badgedInput]) => {\n const fieldValid = inputElement.checkValidity();\n isValid = isValid && fieldValid;\n if (!fieldValid) {\n badgedInput.error = true;\n }\n });\n\n if (!isValid) {\n this.errorMessage.innerText = 'Please enter any missing contact information below';\n } else {\n this.errorMessage.innerText = '';\n }\n\n return isValid;\n }\n\n focus(): void {\n this.emailField.focus();\n }\n\n /** @inheritdoc */\n render(): TemplateResult {\n return html`\n <div id=\"donation-contact-form-error-message\"></div>\n <form>\n <fieldset>\n <div class=\"row\">\n ${this.generateInput({\n id: 'donation-contact-form-email',\n placeholder: 'Email',\n required: true,\n fieldType: 'email',\n name: 'email',\n autocomplete: 'email',\n maxlength: 255,\n icon: emailImg,\n })}\n </div>\n </fieldset>\n\n <fieldset>\n <div class=\"row\">\n ${this.generateInput({\n id: 'donation-contact-form-first-name',\n placeholder: 'First name',\n name: 'fname',\n required: true,\n maxlength: 255,\n autocomplete: 'given-name',\n icon: userIcon,\n })}\n </div>\n <div class=\"row\">\n ${this.generateInput({\n id: 'donation-contact-form-last-name',\n placeholder: 'Last name',\n name: 'lname',\n autocomplete: 'family-name',\n required: true,\n maxlength: 255,\n })}\n </div>\n </fieldset>\n <fieldset>\n <div class=\"row\">\n ${this.generateInput({\n id: 'donation-contact-form-street-address',\n placeholder: 'Address Line 1',\n required: true,\n autocomplete: 'address-line1',\n icon: localePinImg,\n name: 'street-address',\n })}\n </div>\n <div class=\"row\">\n ${this.generateInput({\n id: 'donation-contact-form-extended-address',\n placeholder: 'Address Line 2 (optional)',\n autocomplete: 'address-line2',\n required: false,\n name: 'extended-address',\n })}\n </div>\n <div class=\"row\">\n ${this.generateInput({\n id: 'donation-contact-form-locality',\n placeholder: 'City',\n autocomplete: 'address-level2',\n required: true,\n name: 'locality',\n })}\n </div>\n <div class=\"row\">\n ${this.generateInput({\n id: 'donation-contact-form-region',\n placeholder: 'State / Province',\n autocomplete: 'address-level1',\n required: true,\n name: 'region',\n })}\n ${this.generateInput({\n id: 'donation-contact-form-postal-code',\n placeholder: 'Zip / Postal',\n autocomplete: 'postal-code',\n required: true,\n name: 'postal',\n maxlength: 9,\n // must start with a character, then may contain spaces\n validationPattern: '[a-zA-Z\\\\-\\\\d]+[a-zA-Z\\\\-\\\\d\\\\s]*',\n iconSpaceOption: SpacerOption.CompressSpace,\n })}\n </div>\n <div class=\"row\">\n ${this.countrySelectorTemplate}\n </div>\n </fieldset>\n </form>\n ${this.getStyles}\n `;\n }\n\n private get countrySelectorTemplate(): TemplateResult {\n return html`\n <badged-input>\n <select id=\"donation-contact-form-countryCodeAlpha2\"\n @change=${(e: Event) => {\n const currCountry = this.selectedCountry;\n this.selectedCountry = (e.target as HTMLInputElement)?.value ? (e.target as HTMLInputElement)?.value as string : currCountry;\n // update required visual cue on region/state/province & postal code fields\n if (this.selectedCountry === 'US') {\n this.postalBadgedInput?.setAttribute('required', '');\n this.postalCodeField?.setAttribute('required', '');\n this.regionBadgedInput?.setAttribute('required', '');\n this.regionField?.setAttribute('required', '');\n } else {\n this.postalBadgedInput?.removeAttribute('required');\n this.postalCodeField?.removeAttribute('required');\n this.regionBadgedInput?.removeAttribute('required');\n this.regionField?.removeAttribute('required');\n }\n }}>\n ${Object.keys(countries).map(key => {\n const name = countries[key];\n return html`\n <option value=${key} ?selected=${key === this.selectedCountry}>${name}</option>\n `;\n })}\n </select>\n </badged-input>\n `;\n }\n\n /** @inheritdoc */\n createRenderRoot(): this {\n // Render template without shadow DOM. Note that shadow DOM features like\n // encapsulated CSS and slots are unavailable.\n // Form autofill does not work properly in the shadow DOM\n // so we need our form fields in the light DOM\n return this;\n }\n\n // reset the error state when the user focuses the input\n private inputFocused(e: KeyboardEvent): void {\n this.errorMessage.innerText = '';\n const input = e.target as HTMLInputElement;\n const inputIdentifier = input.id;\n const badgedInput = this.querySelector(`badged-input.${inputIdentifier}`) as BadgedInput;\n badgedInput.error = false;\n }\n\n private generateInput(options: {\n id: string;\n placeholder: string;\n required?: boolean;\n fieldType?: 'text' | 'email';\n autocomplete?: AutoCompleteFieldOptions;\n maxlength?: number;\n name: string;\n icon?: TemplateResult;\n iconSpaceOption?: SpacerOption;\n validationPattern?: string;\n }): TemplateResult {\n const required = options.required ?? true;\n const fieldType = options.fieldType ?? 'text';\n const iconOption = options.iconSpaceOption ?? SpacerOption.LeaveSpace;\n\n return html`\n <badged-input\n class=${options.id}\n .icon=${options.icon}\n .iconSpaceOption=${iconOption}\n ?required=${options.required}\n >\n <label for=${options.id}>${options.placeholder}</label>\n <input\n type=${fieldType}\n id=${options.id}\n class=\"donation-contact-form-input\"\n name=${options.name}\n aria-label=${options.placeholder}\n placeholder=${options.placeholder}\n maxlength=${ifDefined(options.maxlength)}\n autocomplete=${options.autocomplete ?? 'on'}\n pattern=${ifDefined(options.validationPattern)}\n @focus=${this.inputFocused}\n ?required=${required}\n />\n </badged-input>\n `;\n }\n\n get donorContactInfo(): DonorContactInfo {\n return new DonorContactInfo({\n billing: this.billingInfo,\n customer: this.contactInfo,\n });\n }\n\n get billingInfo(): BillingInfo {\n const billingInfo = new BillingInfo({\n streetAddress: this.streetAddressField.value,\n extendedAddress: this.extendedAddressField.value,\n locality: this.localityField.value,\n region: this.regionField.value,\n postalCode: this.postalCodeField.value,\n countryCodeAlpha2: this.countryCodeAlpha2Field.value,\n });\n return billingInfo;\n }\n\n get contactInfo(): CustomerInfo {\n return new CustomerInfo({\n email: this.emailField.value,\n firstName: this.firstNameField.value,\n lastName: this.lastNameField.value,\n });\n }\n\n /**\n * This is not the normal LitElement styles block.\n *\n * This element uses the clear DOM instead of the shadow DOM so it can't use\n * the shadowRoot's isolated styling. This is a bit of a workaround to keep all of\n * the styling local by writing out our own <style> tag and just be careful about\n * the selectors since they will leak outside of this component.\n *\n * @readonly\n * @private\n * @type {TemplateResult}\n * @memberof ContactForm\n */\n private get getStyles(): TemplateResult {\n const noIconSpacerWidth = css`var(--badgedInputNoIconSpacerWidth, 3rem)`;\n const iconSpacerWidth = css`var(--badgedInputIconSpacerWidth, 5rem)`;\n\n const fieldSetSpacing = css`var(--fieldSetSpacing, 1rem)`;\n const fieldFontFamily = css`var(--fontFamily, \"Helvetica Neue\", Helvetica, Arial, sans-serif)`;\n const fieldFontSize = css`var(--contactFieldFontSize, 1.6rem)`;\n const fieldFontColor = css`var(--inputFieldFontColor, #333)`;\n\n const iconFieldWidth = css`calc(100% - ${iconSpacerWidth})`;\n const noIconFieldWidth = css`calc(100% - ${noIconSpacerWidth})`;\n\n return html`\n <style>\n /*\n **NOTE**\n This element is in the lightDOM so be sure to prefix all styles\n with \"contact-form\" so styles don't leak.\n */\n contact-form fieldset {\n border: 0;\n padding: 0;\n margin: 0;\n margin-bottom: ${fieldSetSpacing};\n background-color: white;\n }\n\n /* These 1px and 0 margins in the next few selectors are to account for the\n double outlines caused by the fields being right next to each other */\n contact-form .row {\n display: flex;\n margin: -1px 0 0 0;\n }\n\n contact-form fieldset .row:first-child {\n margin-top: 0;\n }\n\n contact-form badged-input.donation-contact-form-region {\n width: 60%;\n }\n\n contact-form badged-input.donation-contact-form-postal-code {\n width: 40%;\n }\n\n contact-form #donation-contact-form-region {\n width: ${iconFieldWidth};\n }\n\n contact-form #donation-contact-form-postal-code {\n width: ${noIconFieldWidth};\n }\n\n contact-form #donation-contact-form-error-message {\n color: red;\n font-size: 1.4rem;\n margin-bottom: 0.6rem;\n }\n\n contact-form #donation-contact-form-last-name {\n width: ${noIconFieldWidth};\n }\n\n /* only show for screen readers */\n contact-form label {\n position: absolute;\n left: -10000px;\n top: auto;\n width: 1px;\n height: 1px;\n overflow: hidden;\n }\n\n contact-form .donation-contact-form-input {\n width: ${iconFieldWidth};\n border: 0;\n outline: 0;\n background: transparent;\n font-weight: bold;\n color: ${fieldFontColor};\n font-size: ${fieldFontSize};\n padding: 0;\n font-family: ${fieldFontFamily};\n }\n\n contact-form .donation-contact-form-input::placeholder {\n color: revert;\n }\n\n contact-form #donation-contact-form-countryCodeAlpha2 {\n width: ${iconFieldWidth};\n height: 100%;\n box-sizing: border-box;\n font-weight: bold;\n font-size: ${fieldFontSize};\n font-family: ${fieldFontFamily};\n border: 0;\n background: #fff;\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n }\n </style>\n `;\n }\n}\n"]}
|
|
@@ -58,6 +58,17 @@ describe('Donation Form Controller', () => {
|
|
|
58
58
|
yield elementUpdated(donationForm);
|
|
59
59
|
yield promisedSleep(100);
|
|
60
60
|
const contactForm = document.querySelector('contact-form');
|
|
61
|
+
// // check Zip Code Requirements
|
|
62
|
+
// expect((contactForm.querySelector('#donation-contact-form-countryCodeAlpha2') as HTMLSelectElement).value).to.equal('US');
|
|
63
|
+
// expect((contactForm.querySelector('#donation-contact-form-postal-code') as HTMLInputElement).hasAttribute('required')).to.be.true;
|
|
64
|
+
// // change country to outside US
|
|
65
|
+
// contactForm.querySelector('#donation-contact-form-countryCodeAlpha2')!.querySelector('option[value="AX"]')?.setAttribute('selected', 'selected');
|
|
66
|
+
// await promisedSleep(500);
|
|
67
|
+
// // country is now set to Aland Islands
|
|
68
|
+
// expect((contactForm.querySelector('#donation-contact-form-countryCodeAlpha2') as HTMLSelectElement).value).to.equal('AX');
|
|
69
|
+
// // zip input is no longer required
|
|
70
|
+
// expect((contactForm.querySelector('#donation-contact-form-postal-code') as HTMLInputElement).hasAttribute('required')).to.equal(333333);
|
|
71
|
+
// // check validation
|
|
61
72
|
yield fillInContactForm(contactForm);
|
|
62
73
|
// verify the Donate button is still disabled
|
|
63
74
|
const donateButton = (_c = donationForm === null || donationForm === void 0 ? void 0 : donationForm.shadowRoot) === null || _c === void 0 ? void 0 : _c.querySelector('#donate-button');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"donation-form-controller.test.js","sourceRoot":"","sources":["../../../test/tests/donation-form-controller.test.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { html, fixture, expect, elementUpdated, oneEvent } from '@open-wc/testing';\n\nimport '../../src/donation-form-controller';\nimport { DonationFormController } from '../../src/donation-form-controller';\nimport { MockGrecaptcha, MockGrecaptchaMode } from '../mocks/payment-clients/mock-grecaptcha';\nimport { HostingEnvironment } from '../../src/braintree-manager/braintree-interfaces';\nimport { MockEndpointManager } from '../mocks/mock-endpoint-manager';\nimport { MockPaymentClients } from '../mocks/mock-payment-clients';\nimport { ContactForm } from '../../src/form-elements/contact-form/contact-form';\nimport { fillInContactForm } from '../helpers/fillInContactForm';\nimport { promisedSleep } from '../../src/util/promisedSleep';\nimport { MockModalManager } from '../mocks/mock-modal-manager';\nimport { MockHostedFieldsClient } from '../mocks/payment-clients/mock-hostedfields-client';\nimport { DonationForm } from '../../src/donation-form';\nimport { PaymentSelector } from '../../src/form-elements/payment-selector';\nimport { DonationFormHeader } from '../../src/form-elements/header/donation-form-header';\nimport { DonationFormEditDonation } from '@internetarchive/donation-form-edit-donation';\nimport { MockPaymentFlowHandlers } from '../mocks/flow-handlers/mock-payment-flow-handlers';\nimport { MockAnalyticsManager } from '@internetarchive/analytics-manager/dist/test/mock-analytics-manager';\n\ndescribe('Donation Form Controller', () => {\n beforeEach(() => {\n (window['grecaptcha' as any] as any) = new MockGrecaptcha(MockGrecaptchaMode.Success);\n });\n\n afterEach(() => {\n delete window['grecaptcha' as any];\n });\n\n it('has no shadowRoot', async () => {\n const el = (await fixture(html`\n <donation-form-controller></donation-form-controller>\n `)) as DonationFormController;\n\n expect(el.shadowRoot).to.equal(null);\n });\n\n it('can submit a donation', async () => {\n const mockAnalytics = new MockAnalyticsManager();\n const controller = (await fixture(html`\n <donation-form-controller .analyticsHandler=${mockAnalytics}> </donation-form-controller>\n `)) as DonationFormController;\n\n // configure the donation-form-controller\n const recaptchaElement = (await fixture(\n html`\n <div></div>\n `,\n )) as HTMLElement;\n const endpointManager = new MockEndpointManager();\n const paymentClients = new MockPaymentClients();\n const modalManager = new MockModalManager();\n controller.paymentClients = paymentClients;\n controller.modalManager = modalManager;\n controller.environment = HostingEnvironment.Development;\n controller.recaptchaElement = recaptchaElement;\n controller.endpointManager = endpointManager;\n controller.braintreeAuthToken = 'foo';\n controller.recaptchaSiteKey = 'bar';\n controller.venmoProfileId = 'baz';\n controller.referrer = 'test-referrer';\n controller.loggedInUser = 'test-user';\n\n // grab some internal elements to interact with\n const donationForm: DonationForm = controller.querySelector('donation-form') as DonationForm;\n const paymentSelector: PaymentSelector = donationForm?.shadowRoot?.querySelector(\n 'payment-selector',\n ) as PaymentSelector;\n const creditCardButton = paymentSelector?.shadowRoot?.querySelector('.credit-card-button');\n\n // click on the credit card button\n const ccClickEvent = new MouseEvent('click');\n creditCardButton?.dispatchEvent(ccClickEvent);\n\n // clicking on the credit card button will show the contact form so wait for it to be updated\n await elementUpdated(donationForm);\n await promisedSleep(100);\n const contactForm = document.querySelector('contact-form') as ContactForm;\n await fillInContactForm(contactForm);\n\n // verify the Donate button is still disabled\n const donateButton = donationForm?.shadowRoot?.querySelector(\n '#donate-button',\n ) as HTMLButtonElement;\n\n // simulates after the user has input all of the credit card fields\n const hostedFields = (await paymentClients.hostedFields.get()) as MockHostedFieldsClient;\n hostedFields.emitValidityChangedEvent(true);\n await promisedSleep(100);\n\n // verify that the donate button has become enabled and no request has been submitted\n expect(donateButton.disabled).to.equal(false);\n expect(endpointManager.requestSubmitted).to.equal(undefined);\n\n // click the donate button\n const donateClickEvent = new MouseEvent('click');\n donateButton?.dispatchEvent(donateClickEvent);\n await promisedSleep(100);\n\n expect(mockAnalytics.sendEventOptions?.action).to.equal('PaymentFlowStarted');\n\n // verify that a payload has been requested to be submitted to the backend\n expect(endpointManager.requestSubmitted).to.not.equal(undefined);\n });\n\n it('sends Viewed analytics when it first updates', async () => {\n const mockAnalytics = new MockAnalyticsManager();\n const analyticsCategory = 'FooCategory';\n (await fixture(html`\n <donation-form-controller\n ?showCreditCardButtonText=${true}\n .analyticsCategory=${analyticsCategory}\n .analyticsHandler=${mockAnalytics}\n >\n </donation-form-controller>\n `)) as DonationFormController;\n expect(mockAnalytics.sendEventOptions?.category).to.equal(analyticsCategory);\n expect(mockAnalytics.sendEventOptions?.action).to.equal('Viewed');\n });\n\n it('sends DonationInfoChanged analytics when donation info changes', async () => {\n const mockAnalytics = new MockAnalyticsManager();\n const analyticsCategory = 'FooCategory';\n const controller = (await fixture(html`\n <donation-form-controller\n ?showCreditCardButtonText=${true}\n .analyticsCategory=${analyticsCategory}\n .analyticsHandler=${mockAnalytics}\n >\n </donation-form-controller>\n `)) as DonationFormController;\n\n const donationForm: DonationForm = controller.querySelector('donation-form') as DonationForm;\n const donationHeader = donationForm.shadowRoot?.querySelector(\n 'donation-form-header',\n ) as DonationFormHeader;\n const editDonation = donationHeader?.shadowRoot?.querySelector(\n 'donation-form-edit-donation',\n ) as DonationFormEditDonation;\n const monthlyOption = editDonation?.shadowRoot?.querySelector('#donationType-monthly-option');\n const clickEvent = new MouseEvent('click');\n monthlyOption?.dispatchEvent(clickEvent);\n\n expect(mockAnalytics.sendEventOptions?.category).to.equal(analyticsCategory);\n expect(mockAnalytics.sendEventOptions?.action).to.equal('DonationInfoChanged');\n });\n\n it('sends ProviderSelected analytics', async () => {\n const mockAnalytics = new MockAnalyticsManager();\n const analyticsCategory = 'FooCategory';\n const controller = (await fixture(html`\n <donation-form-controller\n ?showCreditCardButtonText=${true}\n .analyticsCategory=${analyticsCategory}\n .analyticsHandler=${mockAnalytics}\n >\n </donation-form-controller>\n `)) as DonationFormController;\n\n const donationForm: DonationForm = controller.querySelector('donation-form') as DonationForm;\n const paymentSelector = donationForm.shadowRoot?.querySelector(\n 'payment-selector',\n ) as PaymentSelector;\n\n // on the first payment provider chosen, the previousPaymentProvider is undefined\n const creditCardButton = paymentSelector.shadowRoot?.querySelector(\n '.credit-card-button',\n ) as HTMLButtonElement;\n setTimeout(() => {\n const ccClickEvent = new MouseEvent('click');\n creditCardButton.dispatchEvent(ccClickEvent);\n });\n await oneEvent(donationForm, 'paymentProviderSelected');\n expect(mockAnalytics.sendEventOptions?.action).to.equal('ProviderFirstSelected-CreditCard');\n\n // on subsequent payment provider choices, the previousPaymentProvider is populated\n const venmoButton = paymentSelector.shadowRoot?.querySelector('.venmo') as HTMLButtonElement;\n setTimeout(() => {\n const venmoClickEvent = new MouseEvent('click');\n venmoButton.dispatchEvent(venmoClickEvent);\n });\n await oneEvent(donationForm, 'paymentProviderSelected');\n expect(mockAnalytics.sendEventOptions?.action).to.equal('ProviderChangedTo-Venmo');\n });\n\n it('sends PaymentFlowCancelled analytics', async () => {\n const mockAnalytics = new MockAnalyticsManager();\n const analyticsCategory = 'FooCategory';\n const controller = (await fixture(html`\n <donation-form-controller\n ?showCreditCardButtonText=${true}\n .analyticsCategory=${analyticsCategory}\n .analyticsHandler=${mockAnalytics}\n >\n </donation-form-controller>\n `)) as DonationFormController;\n\n const donationForm: DonationForm = controller.querySelector('donation-form') as DonationForm;\n const flowHandlers = new MockPaymentFlowHandlers();\n donationForm.paymentFlowHandlers = flowHandlers;\n await elementUpdated(donationForm);\n await promisedSleep(250);\n flowHandlers.paypalHandler.emitPaymentCancelledEvent();\n expect(mockAnalytics.sendEventOptions?.action).to.equal('PaymentFlowCancelled');\n expect(mockAnalytics.sendEventOptions?.label).to.equal('PayPal');\n });\n\n it('sends PaymentFlowError analytics', async () => {\n const mockAnalytics = new MockAnalyticsManager();\n const analyticsCategory = 'FooCategory';\n const controller = (await fixture(html`\n <donation-form-controller\n ?showCreditCardButtonText=${true}\n .analyticsCategory=${analyticsCategory}\n .analyticsHandler=${mockAnalytics}\n >\n </donation-form-controller>\n `)) as DonationFormController;\n\n const donationForm: DonationForm = controller.querySelector('donation-form') as DonationForm;\n const flowHandlers = new MockPaymentFlowHandlers();\n donationForm.paymentFlowHandlers = flowHandlers;\n await elementUpdated(donationForm);\n await promisedSleep(250);\n flowHandlers.paypalHandler.emitPaymentErrorEvent();\n expect(mockAnalytics.sendEventOptions?.action).to.equal('PaymentFlowError');\n expect(mockAnalytics.sendEventOptions?.label).to.equal('PayPal-foo-error');\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"donation-form-controller.test.js","sourceRoot":"","sources":["../../../test/tests/donation-form-controller.test.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { html, fixture, expect, elementUpdated, oneEvent } from '@open-wc/testing';\n\nimport '../../src/donation-form-controller';\nimport { DonationFormController } from '../../src/donation-form-controller';\nimport { MockGrecaptcha, MockGrecaptchaMode } from '../mocks/payment-clients/mock-grecaptcha';\nimport { HostingEnvironment } from '../../src/braintree-manager/braintree-interfaces';\nimport { MockEndpointManager } from '../mocks/mock-endpoint-manager';\nimport { MockPaymentClients } from '../mocks/mock-payment-clients';\nimport { ContactForm } from '../../src/form-elements/contact-form/contact-form';\nimport { fillInContactForm } from '../helpers/fillInContactForm';\nimport { promisedSleep } from '../../src/util/promisedSleep';\nimport { MockModalManager } from '../mocks/mock-modal-manager';\nimport { MockHostedFieldsClient } from '../mocks/payment-clients/mock-hostedfields-client';\nimport { DonationForm } from '../../src/donation-form';\nimport { PaymentSelector } from '../../src/form-elements/payment-selector';\nimport { DonationFormHeader } from '../../src/form-elements/header/donation-form-header';\nimport { DonationFormEditDonation } from '@internetarchive/donation-form-edit-donation';\nimport { MockPaymentFlowHandlers } from '../mocks/flow-handlers/mock-payment-flow-handlers';\nimport { MockAnalyticsManager } from '@internetarchive/analytics-manager/dist/test/mock-analytics-manager';\n\ndescribe('Donation Form Controller', () => {\n beforeEach(() => {\n (window['grecaptcha' as any] as any) = new MockGrecaptcha(MockGrecaptchaMode.Success);\n });\n\n afterEach(() => {\n delete window['grecaptcha' as any];\n });\n\n it('has no shadowRoot', async () => {\n const el = (await fixture(html`\n <donation-form-controller></donation-form-controller>\n `)) as DonationFormController;\n\n expect(el.shadowRoot).to.equal(null);\n });\n\n it('can submit a donation', async () => {\n const mockAnalytics = new MockAnalyticsManager();\n const controller = (await fixture(html`\n <donation-form-controller .analyticsHandler=${mockAnalytics}> </donation-form-controller>\n `)) as DonationFormController;\n\n // configure the donation-form-controller\n const recaptchaElement = (await fixture(\n html`\n <div></div>\n `,\n )) as HTMLElement;\n const endpointManager = new MockEndpointManager();\n const paymentClients = new MockPaymentClients();\n const modalManager = new MockModalManager();\n controller.paymentClients = paymentClients;\n controller.modalManager = modalManager;\n controller.environment = HostingEnvironment.Development;\n controller.recaptchaElement = recaptchaElement;\n controller.endpointManager = endpointManager;\n controller.braintreeAuthToken = 'foo';\n controller.recaptchaSiteKey = 'bar';\n controller.venmoProfileId = 'baz';\n controller.referrer = 'test-referrer';\n controller.loggedInUser = 'test-user';\n\n // grab some internal elements to interact with\n const donationForm: DonationForm = controller.querySelector('donation-form') as DonationForm;\n const paymentSelector: PaymentSelector = donationForm?.shadowRoot?.querySelector(\n 'payment-selector',\n ) as PaymentSelector;\n const creditCardButton = paymentSelector?.shadowRoot?.querySelector('.credit-card-button');\n\n // click on the credit card button\n const ccClickEvent = new MouseEvent('click');\n creditCardButton?.dispatchEvent(ccClickEvent);\n\n // clicking on the credit card button will show the contact form so wait for it to be updated\n await elementUpdated(donationForm);\n await promisedSleep(100);\n const contactForm = document.querySelector('contact-form') as ContactForm;\n\n // // check Zip Code Requirements\n\n // expect((contactForm.querySelector('#donation-contact-form-countryCodeAlpha2') as HTMLSelectElement).value).to.equal('US');\n // expect((contactForm.querySelector('#donation-contact-form-postal-code') as HTMLInputElement).hasAttribute('required')).to.be.true;\n\n // // change country to outside US\n // contactForm.querySelector('#donation-contact-form-countryCodeAlpha2')!.querySelector('option[value=\"AX\"]')?.setAttribute('selected', 'selected');\n // await promisedSleep(500);\n\n // // country is now set to Aland Islands\n // expect((contactForm.querySelector('#donation-contact-form-countryCodeAlpha2') as HTMLSelectElement).value).to.equal('AX');\n\n // // zip input is no longer required\n // expect((contactForm.querySelector('#donation-contact-form-postal-code') as HTMLInputElement).hasAttribute('required')).to.equal(333333);\n\n // // check validation\n\n await fillInContactForm(contactForm);\n\n // verify the Donate button is still disabled\n const donateButton = donationForm?.shadowRoot?.querySelector(\n '#donate-button',\n ) as HTMLButtonElement;\n\n // simulates after the user has input all of the credit card fields\n const hostedFields = (await paymentClients.hostedFields.get()) as MockHostedFieldsClient;\n hostedFields.emitValidityChangedEvent(true);\n await promisedSleep(100);\n\n // verify that the donate button has become enabled and no request has been submitted\n expect(donateButton.disabled).to.equal(false);\n expect(endpointManager.requestSubmitted).to.equal(undefined);\n\n // click the donate button\n const donateClickEvent = new MouseEvent('click');\n donateButton?.dispatchEvent(donateClickEvent);\n await promisedSleep(100);\n\n expect(mockAnalytics.sendEventOptions?.action).to.equal('PaymentFlowStarted');\n\n // verify that a payload has been requested to be submitted to the backend\n expect(endpointManager.requestSubmitted).to.not.equal(undefined);\n });\n\n it('sends Viewed analytics when it first updates', async () => {\n const mockAnalytics = new MockAnalyticsManager();\n const analyticsCategory = 'FooCategory';\n (await fixture(html`\n <donation-form-controller\n ?showCreditCardButtonText=${true}\n .analyticsCategory=${analyticsCategory}\n .analyticsHandler=${mockAnalytics}\n >\n </donation-form-controller>\n `)) as DonationFormController;\n expect(mockAnalytics.sendEventOptions?.category).to.equal(analyticsCategory);\n expect(mockAnalytics.sendEventOptions?.action).to.equal('Viewed');\n });\n\n it('sends DonationInfoChanged analytics when donation info changes', async () => {\n const mockAnalytics = new MockAnalyticsManager();\n const analyticsCategory = 'FooCategory';\n const controller = (await fixture(html`\n <donation-form-controller\n ?showCreditCardButtonText=${true}\n .analyticsCategory=${analyticsCategory}\n .analyticsHandler=${mockAnalytics}\n >\n </donation-form-controller>\n `)) as DonationFormController;\n\n const donationForm: DonationForm = controller.querySelector('donation-form') as DonationForm;\n const donationHeader = donationForm.shadowRoot?.querySelector(\n 'donation-form-header',\n ) as DonationFormHeader;\n const editDonation = donationHeader?.shadowRoot?.querySelector(\n 'donation-form-edit-donation',\n ) as DonationFormEditDonation;\n const monthlyOption = editDonation?.shadowRoot?.querySelector('#donationType-monthly-option');\n const clickEvent = new MouseEvent('click');\n monthlyOption?.dispatchEvent(clickEvent);\n\n expect(mockAnalytics.sendEventOptions?.category).to.equal(analyticsCategory);\n expect(mockAnalytics.sendEventOptions?.action).to.equal('DonationInfoChanged');\n });\n\n it('sends ProviderSelected analytics', async () => {\n const mockAnalytics = new MockAnalyticsManager();\n const analyticsCategory = 'FooCategory';\n const controller = (await fixture(html`\n <donation-form-controller\n ?showCreditCardButtonText=${true}\n .analyticsCategory=${analyticsCategory}\n .analyticsHandler=${mockAnalytics}\n >\n </donation-form-controller>\n `)) as DonationFormController;\n\n const donationForm: DonationForm = controller.querySelector('donation-form') as DonationForm;\n const paymentSelector = donationForm.shadowRoot?.querySelector(\n 'payment-selector',\n ) as PaymentSelector;\n\n // on the first payment provider chosen, the previousPaymentProvider is undefined\n const creditCardButton = paymentSelector.shadowRoot?.querySelector(\n '.credit-card-button',\n ) as HTMLButtonElement;\n setTimeout(() => {\n const ccClickEvent = new MouseEvent('click');\n creditCardButton.dispatchEvent(ccClickEvent);\n });\n await oneEvent(donationForm, 'paymentProviderSelected');\n expect(mockAnalytics.sendEventOptions?.action).to.equal('ProviderFirstSelected-CreditCard');\n\n // on subsequent payment provider choices, the previousPaymentProvider is populated\n const venmoButton = paymentSelector.shadowRoot?.querySelector('.venmo') as HTMLButtonElement;\n setTimeout(() => {\n const venmoClickEvent = new MouseEvent('click');\n venmoButton.dispatchEvent(venmoClickEvent);\n });\n await oneEvent(donationForm, 'paymentProviderSelected');\n expect(mockAnalytics.sendEventOptions?.action).to.equal('ProviderChangedTo-Venmo');\n });\n\n it('sends PaymentFlowCancelled analytics', async () => {\n const mockAnalytics = new MockAnalyticsManager();\n const analyticsCategory = 'FooCategory';\n const controller = (await fixture(html`\n <donation-form-controller\n ?showCreditCardButtonText=${true}\n .analyticsCategory=${analyticsCategory}\n .analyticsHandler=${mockAnalytics}\n >\n </donation-form-controller>\n `)) as DonationFormController;\n\n const donationForm: DonationForm = controller.querySelector('donation-form') as DonationForm;\n const flowHandlers = new MockPaymentFlowHandlers();\n donationForm.paymentFlowHandlers = flowHandlers;\n await elementUpdated(donationForm);\n await promisedSleep(250);\n flowHandlers.paypalHandler.emitPaymentCancelledEvent();\n expect(mockAnalytics.sendEventOptions?.action).to.equal('PaymentFlowCancelled');\n expect(mockAnalytics.sendEventOptions?.label).to.equal('PayPal');\n });\n\n it('sends PaymentFlowError analytics', async () => {\n const mockAnalytics = new MockAnalyticsManager();\n const analyticsCategory = 'FooCategory';\n const controller = (await fixture(html`\n <donation-form-controller\n ?showCreditCardButtonText=${true}\n .analyticsCategory=${analyticsCategory}\n .analyticsHandler=${mockAnalytics}\n >\n </donation-form-controller>\n `)) as DonationFormController;\n\n const donationForm: DonationForm = controller.querySelector('donation-form') as DonationForm;\n const flowHandlers = new MockPaymentFlowHandlers();\n donationForm.paymentFlowHandlers = flowHandlers;\n await elementUpdated(donationForm);\n await promisedSleep(250);\n flowHandlers.paypalHandler.emitPaymentErrorEvent();\n expect(mockAnalytics.sendEventOptions?.action).to.equal('PaymentFlowError');\n expect(mockAnalytics.sendEventOptions?.label).to.equal('PayPal-foo-error');\n });\n});\n"]}
|
package/package.json
CHANGED
|
@@ -52,7 +52,7 @@ export class ContactForm extends LitElement {
|
|
|
52
52
|
@query('form') form!: HTMLFormElement;
|
|
53
53
|
|
|
54
54
|
/** @keyof countries */
|
|
55
|
-
@property({ type: String }) selectedCountry
|
|
55
|
+
@property({ type: String }) selectedCountry = 'US';
|
|
56
56
|
|
|
57
57
|
reportValidity(): boolean {
|
|
58
58
|
const fieldBadgedInputs: Array<[HTMLInputElement, BadgedInput]> = [
|
|
@@ -195,13 +195,17 @@ export class ContactForm extends LitElement {
|
|
|
195
195
|
@change=${(e: Event) => {
|
|
196
196
|
const currCountry = this.selectedCountry;
|
|
197
197
|
this.selectedCountry = (e.target as HTMLInputElement)?.value ? (e.target as HTMLInputElement)?.value as string : currCountry;
|
|
198
|
-
// update required visual cue on postal code
|
|
198
|
+
// update required visual cue on region/state/province & postal code fields
|
|
199
199
|
if (this.selectedCountry === 'US') {
|
|
200
200
|
this.postalBadgedInput?.setAttribute('required', '');
|
|
201
201
|
this.postalCodeField?.setAttribute('required', '');
|
|
202
|
+
this.regionBadgedInput?.setAttribute('required', '');
|
|
203
|
+
this.regionField?.setAttribute('required', '');
|
|
202
204
|
} else {
|
|
203
205
|
this.postalBadgedInput?.removeAttribute('required');
|
|
204
206
|
this.postalCodeField?.removeAttribute('required');
|
|
207
|
+
this.regionBadgedInput?.removeAttribute('required');
|
|
208
|
+
this.regionField?.removeAttribute('required');
|
|
205
209
|
}
|
|
206
210
|
}}>
|
|
207
211
|
${Object.keys(countries).map(key => {
|