From 28ceff8b7da63758eecf511737c4cbbd1daabecb Mon Sep 17 00:00:00 2001 From: Abban Dunne Date: Thu, 10 Oct 2024 14:53:50 +0200 Subject: [PATCH] Fix payment field validation issue The composable that handles the error summary and form validation on the donation form was watching a store getter that didn't exist. This fixes that, and adds tests to make sure the error summaries and form submits are handled on all iterations of the donation form. There was also a message about requiring an email being displayed to anonymous donors, which is now removed. --- .../usePersonalDataSectionEventHandlers.ts | 2 +- .../PersonalDataSection.vue | 5 - .../usePersonalDataSectionEventHandlers.ts | 9 +- .../form_fields/CountryAutocompleteField.vue | 2 +- .../pages/donation_form/DonationForm.spec.ts | 386 +++++++++++++- .../DonationFormAlternateOrder.spec.ts | 414 ++++++++++++++++ .../donation_form/DonationFormReceipt.spec.ts | 469 ++++++++++++++++++ .../DonationFormReceiptAlternateOrder.spec.ts | 469 ++++++++++++++++++ .../PersonalDataSection.spec.ts | 173 +------ ...PersonalDataSectionDonationReceipt.spec.ts | 246 +-------- ...nDonationReceiptStreetAutoComplete.spec.ts | 246 +-------- ...sonalDataSectionStreetAutoComplete.spec.ts | 172 +------ 12 files changed, 1734 insertions(+), 859 deletions(-) create mode 100644 tests/unit/components/pages/donation_form/DonationFormAlternateOrder.spec.ts create mode 100644 tests/unit/components/pages/donation_form/DonationFormReceipt.spec.ts create mode 100644 tests/unit/components/pages/donation_form/DonationFormReceiptAlternateOrder.spec.ts diff --git a/src/components/pages/donation_form/DonationReceipt/usePersonalDataSectionEventHandlers.ts b/src/components/pages/donation_form/DonationReceipt/usePersonalDataSectionEventHandlers.ts index 958814e6c..66f5f987c 100644 --- a/src/components/pages/donation_form/DonationReceipt/usePersonalDataSectionEventHandlers.ts +++ b/src/components/pages/donation_form/DonationReceipt/usePersonalDataSectionEventHandlers.ts @@ -76,7 +76,7 @@ export function usePersonalDataSectionEventHandlers( } } ); - store.watch( ( state, getters ) => getters[ 'payment/requiredFieldsAreValid' ], ( isValid: boolean ) => { + store.watch( ( state, getters ) => getters[ 'payment/paymentDataIsValid' ], ( isValid: boolean ) => { if ( !paymentDataIsValid.value && isValid ) { paymentDataIsValid.value = true; } diff --git a/src/components/pages/donation_form/singlePageFormSections/PersonalDataSection.vue b/src/components/pages/donation_form/singlePageFormSections/PersonalDataSection.vue index 3f28596e5..5c37d14d7 100644 --- a/src/components/pages/donation_form/singlePageFormSections/PersonalDataSection.vue +++ b/src/components/pages/donation_form/singlePageFormSections/PersonalDataSection.vue @@ -23,10 +23,6 @@ :initial-address-type="addressType" :address-type-is-invalid="addressTypeIsInvalid" /> -
{{ $t( 'donation_addresstype_option_anonymous_disclaimer' ) }} -
getters[ 'payment/requiredFieldsAreValid' ], ( isValid: boolean ) => { + store.watch( ( state, getters ) => getters[ 'payment/paymentDataIsValid' ], ( isValid: boolean ) => { if ( !paymentDataIsValid.value && isValid ) { paymentDataIsValid.value = true; } diff --git a/src/components/shared/form_fields/CountryAutocompleteField.vue b/src/components/shared/form_fields/CountryAutocompleteField.vue index 525ca4a28..ab97aa6d6 100644 --- a/src/components/shared/form_fields/CountryAutocompleteField.vue +++ b/src/components/shared/form_fields/CountryAutocompleteField.vue @@ -160,7 +160,7 @@ const onBlur = ( selectedCountry: Country ) => { autocompleteIsActive.value = false; if ( !itemWasJustSelectedFromList ) { - emit( 'field-changed', selectedCountry ); + emit( 'field-changed', selectedCountry ?? '' ); } itemWasJustSelectedFromList = false; }, 200 ); diff --git a/tests/unit/components/pages/donation_form/DonationForm.spec.ts b/tests/unit/components/pages/donation_form/DonationForm.spec.ts index f251c8eea..735b48355 100644 --- a/tests/unit/components/pages/donation_form/DonationForm.spec.ts +++ b/tests/unit/components/pages/donation_form/DonationForm.spec.ts @@ -1,12 +1,15 @@ -import { mount, VueWrapper } from '@vue/test-utils'; +import { flushPromises, mount, VueWrapper } from '@vue/test-utils'; import DonationForm from '@src/components/pages/DonationForm.vue'; import countries from '@test/data/countries'; import { AddressValidation } from '@src/view_models/Validation'; import { createFeatureToggle } from '@src/util/createFeatureToggle'; -import PaymentSection from '@src/components/pages/donation_form/singlePageFormSections/PaymentSection.vue'; -import PersonalDataSection from '@src/components/pages/donation_form/singlePageFormSections/PersonalDataSection.vue'; -import { Store } from 'vuex'; -import { createStore, StoreKey } from '@src/store/donation_store'; +import { createStore } from '@src/store/donation_store'; +import { FakeBankValidationResource } from '@test/unit/TestDoubles/FakeBankValidationResource'; +import { nextTick } from 'vue'; +import axios from 'axios'; + +jest.mock( 'axios' ); +const mockedAxios = axios as jest.Mocked; declare global { namespace NodeJS { @@ -16,17 +19,34 @@ declare global { } } +const IBAN = 'DE12500105170648489890'; + +const errorSummaryItemIsFunctional = ( wrapper: VueWrapper, formElement: string, scrollElement: string ): boolean => { + const errorItemExists = wrapper.find( `.error-summary a[href="#${formElement}"]` ).exists(); + const formElementExists = wrapper.find( `#${formElement}` ).exists(); + const scrollElementExists = wrapper.find( `#${scrollElement}` ).exists(); + + return errorItemExists && formElementExists && scrollElementExists; +}; + describe( 'DonationForm.vue', () => { beforeEach( () => { global.window.scrollTo = jest.fn(); + jest.useFakeTimers(); } ); - const getWrapper = ( store: Store = createStore() ): { wrapper: VueWrapper, store: Store } => { - const wrapper = mount( DonationForm, { + afterEach( () => { + jest.clearAllMocks(); + document.getElementsByTagName( 'html' )[ 0 ].innerHTML = ''; + } ); + + const getWrapper = (): VueWrapper => { + const store = createStore(); + return mount( DonationForm, { props: { assetsPath: '', - paymentAmounts: [ 5 ], + paymentAmounts: [ 500, 1000, 2000 ], paymentIntervals: [ 0, 1, 3, 6, 12 ], paymentTypes: [ 'BEZ', 'PPL', 'UEB', 'BTC' ], validateAddressUrl: 'https://example.com/address-check', @@ -36,25 +56,359 @@ describe( 'DonationForm.vue', () => { validateEmailUrl: '', validateBankDataUrl: '', validateLegacyBankDataUrl: '', - salutations: [], - addressValidationPatterns: { postcode: '' } as AddressValidation, + salutations: [ + { + label: 'Mr', + value: 'Mr', + display: 'Mr', + greetings: { + formal: 'Mr', + informal: 'Mr', + lastNameInformal: 'Mr', + }, + }, + { + label: 'Ms', + value: 'Ms', + display: 'Ms', + greetings: { + formal: 'Ms', + informal: 'Ms', + lastNameInformal: 'Ms', + }, + }, + ], + addressValidationPatterns: { postcode: '', country: null } as AddressValidation, }, global: { plugins: [ store ], provide: { - [ StoreKey as symbol ]: store, + bankValidationResource: new FakeBankValidationResource(), }, components: { FeatureToggle: createFeatureToggle( [ 'campaigns.address_pages.legacy' ] ), }, }, + attachTo: document.body, } ); - return { wrapper, store }; }; - it( 'displays payment section and address data section', () => { - const wrapper = getWrapper().wrapper; - expect( wrapper.findComponent( PaymentSection ).exists() ).toBe( true ); - expect( wrapper.findComponent( PersonalDataSection ).exists() ).toBe( true ); + it( 'handles the error summary when no address type was selected before submitting', async () => { + const wrapper = getWrapper(); + + await wrapper.find( '#person-country' ).setValue( 'I am clearly not a country' ); + await wrapper.find( '#person-country' ).trigger( 'blur' ); + await jest.runAllTimersAsync(); + + await wrapper.find( '#submit-btn' ).trigger( 'click' ); + await nextTick(); + await nextTick(); + + expect( errorSummaryItemIsFunctional( wrapper, 'paymentType-0', 'payment-form-type-scroll-target' ) ).toBeTruthy(); + + // Make the IBAN field appear + await wrapper.find( 'input[name="paymentType"][value="BEZ"]' ).trigger( 'change' ); + await wrapper.find( '#submit-btn' ).trigger( 'click' ); + await nextTick(); + await nextTick(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'amount-500', 'payment-form-amount-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'account-number', 'account-number-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'addressType-0', 'address-type-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-salutation-0', 'person-salutation-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-first-name', 'person-first-name-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-last-name', 'person-last-name-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-street', 'person-street-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-post-code', 'person-post-code-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-city', 'person-city-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-country', 'person-country-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-email', 'person-email-scroll-target' ) ).toBeTruthy(); + + await wrapper.find( 'input[name="amount"][value="500"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="addressType"][value="0"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="salutation"][value="Mr"]' ).trigger( 'change' ); + + await wrapper.find( '#account-number' ).setValue( IBAN ); + await wrapper.find( '#account-number' ).trigger( 'blur' ); + + await wrapper.find( '#person-first-name' ).setValue( 'first-name' ); + await wrapper.find( '#person-first-name' ).trigger( 'blur' ); + + await wrapper.find( '#person-last-name' ).setValue( 'last-name' ); + await wrapper.find( '#person-last-name' ).trigger( 'blur' ); + + await wrapper.find( '#person-street' ).setValue( 'street' ); + await wrapper.find( '#person-street' ).trigger( 'blur' ); + + await wrapper.find( '#person-post-code' ).setValue( '12345' ); + await wrapper.find( '#person-post-code' ).trigger( 'blur' ); + + await wrapper.find( '#person-city' ).setValue( 'city' ); + await wrapper.find( '#person-city' ).trigger( 'blur' ); + + await wrapper.find( '#person-country' ).setValue( countries[ 0 ].countryFullName ); + await wrapper.find( '#person-country' ).trigger( 'blur' ); + + await wrapper.find( '#person-email' ).setValue( 'joe@dolan.com' ); + await wrapper.find( '#person-email' ).trigger( 'blur' ); + + await jest.runAllTimersAsync(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeFalsy(); + } ); + + it( 'handles the error summary when person address type was selected before submitting', async () => { + const wrapper = getWrapper(); + + await wrapper.find( 'input[name="addressType"][value="0"]' ).trigger( 'change' ); + await wrapper.find( '#person-country' ).setValue( 'I am clearly not a country' ); + await wrapper.find( '#person-country' ).trigger( 'blur' ); + await jest.runAllTimersAsync(); + + await wrapper.find( '#submit-btn' ).trigger( 'click' ); + await nextTick(); + await nextTick(); + + expect( errorSummaryItemIsFunctional( wrapper, 'paymentType-0', 'payment-form-type-scroll-target' ) ).toBeTruthy(); + + // Make the IBAN field appear + await wrapper.find( 'input[name="paymentType"][value="BEZ"]' ).trigger( 'change' ); + await wrapper.find( '#submit-btn' ).trigger( 'click' ); + await nextTick(); + await nextTick(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'amount-500', 'payment-form-amount-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'account-number', 'account-number-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-salutation-0', 'person-salutation-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-first-name', 'person-first-name-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-last-name', 'person-last-name-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-street', 'person-street-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-post-code', 'person-post-code-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-city', 'person-city-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-country', 'person-country-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-email', 'person-email-scroll-target' ) ).toBeTruthy(); + + await wrapper.find( 'input[name="amount"][value="500"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="salutation"][value="Mr"]' ).trigger( 'change' ); + + await wrapper.find( '#account-number' ).setValue( IBAN ); + await wrapper.find( '#account-number' ).trigger( 'blur' ); + + await wrapper.find( '#person-first-name' ).setValue( 'first-name' ); + await wrapper.find( '#person-first-name' ).trigger( 'blur' ); + + await wrapper.find( '#person-last-name' ).setValue( 'last-name' ); + await wrapper.find( '#person-last-name' ).trigger( 'blur' ); + + await wrapper.find( '#person-street' ).setValue( 'street' ); + await wrapper.find( '#person-street' ).trigger( 'blur' ); + + await wrapper.find( '#person-post-code' ).setValue( '12345' ); + await wrapper.find( '#person-post-code' ).trigger( 'blur' ); + + await wrapper.find( '#person-city' ).setValue( 'city' ); + await wrapper.find( '#person-city' ).trigger( 'blur' ); + + await wrapper.find( '#person-country' ).setValue( countries[ 0 ].countryFullName ); + await wrapper.find( '#person-country' ).trigger( 'blur' ); + + await wrapper.find( '#person-email' ).setValue( 'joe@dolan.com' ); + await wrapper.find( '#person-email' ).trigger( 'blur' ); + + await jest.runAllTimersAsync(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeFalsy(); + } ); + + it( 'handles the error summary when company address type was selected before submitting', async () => { + const wrapper = getWrapper(); + + await wrapper.find( 'input[name="addressType"][value="1"]' ).trigger( 'change' ); + await wrapper.find( '#company-country' ).setValue( 'I am clearly not a country' ); + await wrapper.find( '#company-country' ).trigger( 'blur' ); + await jest.runAllTimersAsync(); + + await wrapper.find( '#submit-btn' ).trigger( 'click' ); + await nextTick(); + await nextTick(); + + expect( errorSummaryItemIsFunctional( wrapper, 'paymentType-0', 'payment-form-type-scroll-target' ) ).toBeTruthy(); + + // Make the IBAN field appear + await wrapper.find( 'input[name="paymentType"][value="BEZ"]' ).trigger( 'change' ); + await wrapper.find( '#submit-btn' ).trigger( 'click' ); + await nextTick(); + await nextTick(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'amount-500', 'payment-form-amount-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'account-number', 'account-number-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'company-company-name', 'company-company-name-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'company-street', 'company-street-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'company-post-code', 'company-post-code-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'company-city', 'company-city-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'company-country', 'company-country-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'company-email', 'company-email-scroll-target' ) ).toBeTruthy(); + + await wrapper.find( 'input[name="amount"][value="500"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="paymentType"][value="PPL"]' ).trigger( 'change' ); + + await wrapper.find( 'input[name="salutation"][value="Mr"]' ).trigger( 'change' ); + + await wrapper.find( '#company-company-name' ).setValue( 'company-name' ); + await wrapper.find( '#company-company-name' ).trigger( 'blur' ); + + await wrapper.find( '#company-street' ).setValue( 'street' ); + await wrapper.find( '#company-street' ).trigger( 'blur' ); + + await wrapper.find( '#company-post-code' ).setValue( '12345' ); + await wrapper.find( '#company-post-code' ).trigger( 'blur' ); + + await wrapper.find( '#company-city' ).setValue( 'city' ); + await wrapper.find( '#company-city' ).trigger( 'blur' ); + + await wrapper.find( '#company-country' ).setValue( countries[ 0 ].countryFullName ); + await wrapper.find( '#company-country' ).trigger( 'blur' ); + + await wrapper.find( '#company-email' ).setValue( 'joe@dolan.com' ); + await wrapper.find( '#company-email' ).trigger( 'blur' ); + + await jest.runAllTimersAsync(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeFalsy(); + } ); + + it( 'handles the error summary when without address type was selected before submitting', async () => { + const wrapper = getWrapper(); + + await wrapper.find( 'input[name="addressType"][value="4"]' ).trigger( 'change' ); + + await wrapper.find( '#submit-btn' ).trigger( 'click' ); + await nextTick(); + await nextTick(); + await flushPromises(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'amount-500', 'payment-form-amount-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'paymentType-0', 'payment-form-type-scroll-target' ) ).toBeTruthy(); + + await wrapper.find( 'input[name="amount"][value="500"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="paymentType"][value="PPL"]' ).trigger( 'change' ); + + await jest.runAllTimersAsync(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeFalsy(); + } ); + + it( 'submits the form for a person', async () => { + mockedAxios.post.mockResolvedValue( { data: { status: 'OK' } } ); + const wrapper = getWrapper(); + + const submitForm = wrapper.find( '#submit-form' ); + submitForm.element.submit = jest.fn(); + + await wrapper.find( 'input[name="amount"][value="500"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="paymentType"][value="BEZ"]' ).trigger( 'change' ); + + await wrapper.find( '#account-number' ).setValue( IBAN ); + await wrapper.find( '#account-number' ).trigger( 'blur' ); + + await wrapper.find( 'input[name="addressType"][value="0"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="salutation"][value="Mr"]' ).trigger( 'change' ); + + await wrapper.find( '#person-first-name' ).setValue( 'first-name' ); + await wrapper.find( '#person-first-name' ).trigger( 'blur' ); + + await wrapper.find( '#person-last-name' ).setValue( 'last-name' ); + await wrapper.find( '#person-last-name' ).trigger( 'blur' ); + + await wrapper.find( '#person-street' ).setValue( 'street' ); + await wrapper.find( '#person-street' ).trigger( 'blur' ); + + await wrapper.find( '#person-post-code' ).setValue( '12345' ); + await wrapper.find( '#person-post-code' ).trigger( 'blur' ); + + await wrapper.find( '#person-city' ).setValue( 'city' ); + await wrapper.find( '#person-city' ).trigger( 'blur' ); + + await jest.runAllTimersAsync(); + + await wrapper.find( '#person-country' ).setValue( countries[ 0 ].countryFullName ); + await wrapper.find( '#person-country' ).trigger( 'blur' ); + + await wrapper.find( '#person-email' ).setValue( 'joe@dolan.com' ); + await wrapper.find( '#person-email' ).trigger( 'blur' ); + + await wrapper.find( '#submit-btn' ).trigger( 'click' ); + + await jest.runAllTimersAsync(); + await flushPromises(); + + expect( submitForm.element.submit ).toHaveBeenCalled(); + } ); + + it( 'submits the form for a company', async () => { + mockedAxios.post.mockResolvedValue( { data: { status: 'OK' } } ); + const wrapper = getWrapper(); + + const submitForm = wrapper.find( '#submit-form' ); + submitForm.element.submit = jest.fn(); + + await wrapper.find( 'input[name="amount"][value="500"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="paymentType"][value="BEZ"]' ).trigger( 'change' ); + + await wrapper.find( '#account-number' ).setValue( IBAN ); + await wrapper.find( '#account-number' ).trigger( 'blur' ); + + await wrapper.find( 'input[name="addressType"][value="1"]' ).trigger( 'change' ); + + await wrapper.find( '#company-company-name' ).setValue( 'company-name' ); + await wrapper.find( '#company-company-name' ).trigger( 'blur' ); + + await wrapper.find( '#company-street' ).setValue( 'street' ); + await wrapper.find( '#company-street' ).trigger( 'blur' ); + + await wrapper.find( '#company-post-code' ).setValue( '12345' ); + await wrapper.find( '#company-post-code' ).trigger( 'blur' ); + + await wrapper.find( '#company-city' ).setValue( 'city' ); + await wrapper.find( '#company-city' ).trigger( 'blur' ); + + await jest.runAllTimersAsync(); + + await wrapper.find( '#company-country' ).setValue( countries[ 0 ].countryFullName ); + await wrapper.find( '#company-country' ).trigger( 'blur' ); + + await wrapper.find( '#company-email' ).setValue( 'joe@dolan.com' ); + await wrapper.find( '#company-email' ).trigger( 'blur' ); + + await wrapper.find( '#submit-btn' ).trigger( 'click' ); + + await jest.runAllTimersAsync(); + await flushPromises(); + + expect( submitForm.element.submit ).toHaveBeenCalled(); + } ); + + it( 'submits the form for anonymous', async () => { + mockedAxios.post.mockResolvedValue( { data: { status: 'OK' } } ); + const wrapper = getWrapper(); + + const submitForm = wrapper.find( '#submit-form' ); + submitForm.element.submit = jest.fn(); + + await wrapper.find( 'input[name="amount"][value="500"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="paymentType"][value="PPL"]' ).trigger( 'change' ); + + await wrapper.find( 'input[name="addressType"][value="4"]' ).trigger( 'change' ); + + await wrapper.find( '#submit-btn' ).trigger( 'click' ); + + await jest.runAllTimersAsync(); + await flushPromises(); + + expect( submitForm.element.submit ).toHaveBeenCalled(); } ); } ); diff --git a/tests/unit/components/pages/donation_form/DonationFormAlternateOrder.spec.ts b/tests/unit/components/pages/donation_form/DonationFormAlternateOrder.spec.ts new file mode 100644 index 000000000..ce34c66e1 --- /dev/null +++ b/tests/unit/components/pages/donation_form/DonationFormAlternateOrder.spec.ts @@ -0,0 +1,414 @@ +import { flushPromises, mount, VueWrapper } from '@vue/test-utils'; +import DonationForm from '@src/components/pages/DonationForm.vue'; +import countries from '@test/data/countries'; +import { AddressValidation } from '@src/view_models/Validation'; +import { createFeatureToggle } from '@src/util/createFeatureToggle'; +import { createStore } from '@src/store/donation_store'; +import { FakeBankValidationResource } from '@test/unit/TestDoubles/FakeBankValidationResource'; +import { nextTick } from 'vue'; +import axios from 'axios'; + +jest.mock( 'axios' ); +const mockedAxios = axios as jest.Mocked; + +declare global { + namespace NodeJS { + interface Global { + window: Window; + } + } +} + +const IBAN = 'DE12500105170648489890'; + +const errorSummaryItemIsFunctional = ( wrapper: VueWrapper, formElement: string, scrollElement: string ): boolean => { + const errorItemExists = wrapper.find( `.error-summary a[href="#${formElement}"]` ).exists(); + const formElementExists = wrapper.find( `#${formElement}` ).exists(); + const scrollElementExists = wrapper.find( `#${scrollElement}` ).exists(); + + return errorItemExists && formElementExists && scrollElementExists; +}; + +describe( 'DonationForm.vue (alternate order for street autocomplete)', () => { + + beforeEach( () => { + global.window.scrollTo = jest.fn(); + jest.useFakeTimers(); + } ); + + afterEach( () => { + jest.clearAllMocks(); + document.getElementsByTagName( 'html' )[ 0 ].innerHTML = ''; + } ); + + const getWrapper = (): VueWrapper => { + const store = createStore(); + return mount( DonationForm, { + props: { + assetsPath: '', + paymentAmounts: [ 500, 1000, 2000 ], + paymentIntervals: [ 0, 1, 3, 6, 12 ], + paymentTypes: [ 'BEZ', 'PPL', 'UEB', 'BTC' ], + validateAddressUrl: 'https://example.com/address-check', + countries: countries, + trackingData: { bannerImpressionCount: 0, impressionCount: 0 }, + campaignValues: { campaign: 'nicholas', keyword: 'cage' }, + validateEmailUrl: '', + validateBankDataUrl: '', + validateLegacyBankDataUrl: '', + salutations: [ + { + label: 'Mr', + value: 'Mr', + display: 'Mr', + greetings: { + formal: 'Mr', + informal: 'Mr', + lastNameInformal: 'Mr', + }, + }, + { + label: 'Ms', + value: 'Ms', + display: 'Ms', + greetings: { + formal: 'Ms', + informal: 'Ms', + lastNameInformal: 'Ms', + }, + }, + ], + addressValidationPatterns: { postcode: '', country: null } as AddressValidation, + }, + global: { + plugins: [ store ], + provide: { + bankValidationResource: new FakeBankValidationResource(), + }, + components: { + FeatureToggle: createFeatureToggle( [ 'campaigns.address_pages.legacy', 'campaigns.address_field_order.new_order' ] ), + }, + }, + attachTo: document.body, + } ); + }; + + it( 'handles the error summary when no address type was selected before submitting', async () => { + const wrapper = getWrapper(); + + await wrapper.find( '#person-country' ).setValue( 'I am clearly not a country' ); + await wrapper.find( '#person-country' ).trigger( 'blur' ); + await jest.runAllTimersAsync(); + + await wrapper.find( '#submit-btn' ).trigger( 'click' ); + await nextTick(); + await nextTick(); + + expect( errorSummaryItemIsFunctional( wrapper, 'paymentType-0', 'payment-form-type-scroll-target' ) ).toBeTruthy(); + + // Make the IBAN field appear + await wrapper.find( 'input[name="paymentType"][value="BEZ"]' ).trigger( 'change' ); + await wrapper.find( '#submit-btn' ).trigger( 'click' ); + await nextTick(); + await nextTick(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'amount-500', 'payment-form-amount-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'account-number', 'account-number-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'addressType-0', 'address-type-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-salutation-0', 'person-salutation-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-first-name', 'person-first-name-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-last-name', 'person-last-name-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-street', 'person-street-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-post-code', 'person-post-code-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-city', 'person-city-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-country', 'person-country-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-email', 'person-email-scroll-target' ) ).toBeTruthy(); + + await wrapper.find( 'input[name="amount"][value="500"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="addressType"][value="0"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="salutation"][value="Mr"]' ).trigger( 'change' ); + + await wrapper.find( '#account-number' ).setValue( IBAN ); + await wrapper.find( '#account-number' ).trigger( 'blur' ); + + await wrapper.find( '#person-first-name' ).setValue( 'first-name' ); + await wrapper.find( '#person-first-name' ).trigger( 'blur' ); + + await wrapper.find( '#person-last-name' ).setValue( 'last-name' ); + await wrapper.find( '#person-last-name' ).trigger( 'blur' ); + + await wrapper.find( '#person-street' ).setValue( 'street' ); + await wrapper.find( '#person-street' ).trigger( 'blur' ); + + await wrapper.find( '#person-post-code' ).setValue( '12345' ); + await wrapper.find( '#person-post-code' ).trigger( 'blur' ); + + await wrapper.find( '#person-city' ).setValue( 'city' ); + await wrapper.find( '#person-city' ).trigger( 'blur' ); + + await wrapper.find( '#person-country' ).setValue( countries[ 0 ].countryFullName ); + await wrapper.find( '#person-country' ).trigger( 'blur' ); + + await wrapper.find( '#person-email' ).setValue( 'joe@dolan.com' ); + await wrapper.find( '#person-email' ).trigger( 'blur' ); + + await jest.runAllTimersAsync(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeFalsy(); + } ); + + it( 'handles the error summary when person address type was selected before submitting', async () => { + const wrapper = getWrapper(); + + await wrapper.find( 'input[name="addressType"][value="0"]' ).trigger( 'change' ); + await wrapper.find( '#person-country' ).setValue( 'I am clearly not a country' ); + await wrapper.find( '#person-country' ).trigger( 'blur' ); + await jest.runAllTimersAsync(); + + await wrapper.find( '#submit-btn' ).trigger( 'click' ); + await nextTick(); + await nextTick(); + + expect( errorSummaryItemIsFunctional( wrapper, 'paymentType-0', 'payment-form-type-scroll-target' ) ).toBeTruthy(); + + // Make the IBAN field appear + await wrapper.find( 'input[name="paymentType"][value="BEZ"]' ).trigger( 'change' ); + await wrapper.find( '#submit-btn' ).trigger( 'click' ); + await nextTick(); + await nextTick(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'amount-500', 'payment-form-amount-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'account-number', 'account-number-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-salutation-0', 'person-salutation-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-first-name', 'person-first-name-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-last-name', 'person-last-name-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-street', 'person-street-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-post-code', 'person-post-code-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-city', 'person-city-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-country', 'person-country-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'person-email', 'person-email-scroll-target' ) ).toBeTruthy(); + + await wrapper.find( 'input[name="amount"][value="500"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="salutation"][value="Mr"]' ).trigger( 'change' ); + + await wrapper.find( '#account-number' ).setValue( IBAN ); + await wrapper.find( '#account-number' ).trigger( 'blur' ); + + await wrapper.find( '#person-first-name' ).setValue( 'first-name' ); + await wrapper.find( '#person-first-name' ).trigger( 'blur' ); + + await wrapper.find( '#person-last-name' ).setValue( 'last-name' ); + await wrapper.find( '#person-last-name' ).trigger( 'blur' ); + + await wrapper.find( '#person-street' ).setValue( 'street' ); + await wrapper.find( '#person-street' ).trigger( 'blur' ); + + await wrapper.find( '#person-post-code' ).setValue( '12345' ); + await wrapper.find( '#person-post-code' ).trigger( 'blur' ); + + await wrapper.find( '#person-city' ).setValue( 'city' ); + await wrapper.find( '#person-city' ).trigger( 'blur' ); + + await wrapper.find( '#person-country' ).setValue( countries[ 0 ].countryFullName ); + await wrapper.find( '#person-country' ).trigger( 'blur' ); + + await wrapper.find( '#person-email' ).setValue( 'joe@dolan.com' ); + await wrapper.find( '#person-email' ).trigger( 'blur' ); + + await jest.runAllTimersAsync(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeFalsy(); + } ); + + it( 'handles the error summary when company address type was selected before submitting', async () => { + const wrapper = getWrapper(); + + await wrapper.find( 'input[name="addressType"][value="1"]' ).trigger( 'change' ); + await wrapper.find( '#company-country' ).setValue( 'I am clearly not a country' ); + await wrapper.find( '#company-country' ).trigger( 'blur' ); + await jest.runAllTimersAsync(); + + await wrapper.find( '#submit-btn' ).trigger( 'click' ); + await nextTick(); + await nextTick(); + + expect( errorSummaryItemIsFunctional( wrapper, 'paymentType-0', 'payment-form-type-scroll-target' ) ).toBeTruthy(); + + // Make the IBAN field appear + await wrapper.find( 'input[name="paymentType"][value="BEZ"]' ).trigger( 'change' ); + await wrapper.find( '#submit-btn' ).trigger( 'click' ); + await nextTick(); + await nextTick(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'amount-500', 'payment-form-amount-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'account-number', 'account-number-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'company-company-name', 'company-company-name-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'company-street', 'company-street-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'company-post-code', 'company-post-code-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'company-city', 'company-city-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'company-country', 'company-country-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'company-email', 'company-email-scroll-target' ) ).toBeTruthy(); + + await wrapper.find( 'input[name="amount"][value="500"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="paymentType"][value="PPL"]' ).trigger( 'change' ); + + await wrapper.find( 'input[name="salutation"][value="Mr"]' ).trigger( 'change' ); + + await wrapper.find( '#company-company-name' ).setValue( 'company-name' ); + await wrapper.find( '#company-company-name' ).trigger( 'blur' ); + + await wrapper.find( '#company-street' ).setValue( 'street' ); + await wrapper.find( '#company-street' ).trigger( 'blur' ); + + await wrapper.find( '#company-post-code' ).setValue( '12345' ); + await wrapper.find( '#company-post-code' ).trigger( 'blur' ); + + await wrapper.find( '#company-city' ).setValue( 'city' ); + await wrapper.find( '#company-city' ).trigger( 'blur' ); + + await wrapper.find( '#company-country' ).setValue( countries[ 0 ].countryFullName ); + await wrapper.find( '#company-country' ).trigger( 'blur' ); + + await wrapper.find( '#company-email' ).setValue( 'joe@dolan.com' ); + await wrapper.find( '#company-email' ).trigger( 'blur' ); + + await jest.runAllTimersAsync(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeFalsy(); + } ); + + it( 'handles the error summary when without address type was selected before submitting', async () => { + const wrapper = getWrapper(); + + await wrapper.find( 'input[name="addressType"][value="4"]' ).trigger( 'change' ); + + await wrapper.find( '#submit-btn' ).trigger( 'click' ); + await nextTick(); + await nextTick(); + await flushPromises(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'amount-500', 'payment-form-amount-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'paymentType-0', 'payment-form-type-scroll-target' ) ).toBeTruthy(); + + await wrapper.find( 'input[name="amount"][value="500"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="paymentType"][value="PPL"]' ).trigger( 'change' ); + + await jest.runAllTimersAsync(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeFalsy(); + } ); + + it( 'submits the form for a person', async () => { + mockedAxios.post.mockResolvedValue( { data: { status: 'OK' } } ); + const wrapper = getWrapper(); + + const submitForm = wrapper.find( '#submit-form' ); + submitForm.element.submit = jest.fn(); + + await wrapper.find( 'input[name="amount"][value="500"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="paymentType"][value="BEZ"]' ).trigger( 'change' ); + + await wrapper.find( '#account-number' ).setValue( IBAN ); + await wrapper.find( '#account-number' ).trigger( 'blur' ); + + await wrapper.find( 'input[name="addressType"][value="0"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="salutation"][value="Mr"]' ).trigger( 'change' ); + + await wrapper.find( '#person-first-name' ).setValue( 'first-name' ); + await wrapper.find( '#person-first-name' ).trigger( 'blur' ); + + await wrapper.find( '#person-last-name' ).setValue( 'last-name' ); + await wrapper.find( '#person-last-name' ).trigger( 'blur' ); + + await wrapper.find( '#person-street' ).setValue( 'street' ); + await wrapper.find( '#person-street' ).trigger( 'blur' ); + + await wrapper.find( '#person-post-code' ).setValue( '12345' ); + await wrapper.find( '#person-post-code' ).trigger( 'blur' ); + + await wrapper.find( '#person-city' ).setValue( 'city' ); + await wrapper.find( '#person-city' ).trigger( 'blur' ); + + await jest.runAllTimersAsync(); + + await wrapper.find( '#person-country' ).setValue( countries[ 0 ].countryFullName ); + await wrapper.find( '#person-country' ).trigger( 'blur' ); + + await wrapper.find( '#person-email' ).setValue( 'joe@dolan.com' ); + await wrapper.find( '#person-email' ).trigger( 'blur' ); + + await wrapper.find( '#submit-btn' ).trigger( 'click' ); + + await jest.runAllTimersAsync(); + await flushPromises(); + + expect( submitForm.element.submit ).toHaveBeenCalled(); + } ); + + it( 'submits the form for a company', async () => { + mockedAxios.post.mockResolvedValue( { data: { status: 'OK' } } ); + const wrapper = getWrapper(); + + const submitForm = wrapper.find( '#submit-form' ); + submitForm.element.submit = jest.fn(); + + await wrapper.find( 'input[name="amount"][value="500"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="paymentType"][value="BEZ"]' ).trigger( 'change' ); + + await wrapper.find( '#account-number' ).setValue( IBAN ); + await wrapper.find( '#account-number' ).trigger( 'blur' ); + + await wrapper.find( 'input[name="addressType"][value="1"]' ).trigger( 'change' ); + + await wrapper.find( '#company-company-name' ).setValue( 'company-name' ); + await wrapper.find( '#company-company-name' ).trigger( 'blur' ); + + await wrapper.find( '#company-street' ).setValue( 'street' ); + await wrapper.find( '#company-street' ).trigger( 'blur' ); + + await wrapper.find( '#company-post-code' ).setValue( '12345' ); + await wrapper.find( '#company-post-code' ).trigger( 'blur' ); + + await wrapper.find( '#company-city' ).setValue( 'city' ); + await wrapper.find( '#company-city' ).trigger( 'blur' ); + + await jest.runAllTimersAsync(); + + await wrapper.find( '#company-country' ).setValue( countries[ 0 ].countryFullName ); + await wrapper.find( '#company-country' ).trigger( 'blur' ); + + await wrapper.find( '#company-email' ).setValue( 'joe@dolan.com' ); + await wrapper.find( '#company-email' ).trigger( 'blur' ); + + await wrapper.find( '#submit-btn' ).trigger( 'click' ); + + await jest.runAllTimersAsync(); + await flushPromises(); + + expect( submitForm.element.submit ).toHaveBeenCalled(); + } ); + + it( 'submits the form for anonymous', async () => { + mockedAxios.post.mockResolvedValue( { data: { status: 'OK' } } ); + const wrapper = getWrapper(); + + const submitForm = wrapper.find( '#submit-form' ); + submitForm.element.submit = jest.fn(); + + await wrapper.find( 'input[name="amount"][value="500"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="paymentType"][value="PPL"]' ).trigger( 'change' ); + + await wrapper.find( 'input[name="addressType"][value="4"]' ).trigger( 'change' ); + + await wrapper.find( '#submit-btn' ).trigger( 'click' ); + + await jest.runAllTimersAsync(); + await flushPromises(); + + expect( submitForm.element.submit ).toHaveBeenCalled(); + } ); +} ); diff --git a/tests/unit/components/pages/donation_form/DonationFormReceipt.spec.ts b/tests/unit/components/pages/donation_form/DonationFormReceipt.spec.ts new file mode 100644 index 000000000..9618cfff8 --- /dev/null +++ b/tests/unit/components/pages/donation_form/DonationFormReceipt.spec.ts @@ -0,0 +1,469 @@ +import { flushPromises, mount, VueWrapper } from '@vue/test-utils'; +import DonationForm from '@src/components/pages/DonationForm.vue'; +import countries from '@test/data/countries'; +import { AddressValidation } from '@src/view_models/Validation'; +import { createFeatureToggle } from '@src/util/createFeatureToggle'; +import { createStore } from '@src/store/donation_store'; +import { FakeBankValidationResource } from '@test/unit/TestDoubles/FakeBankValidationResource'; +import { nextTick } from 'vue'; +import axios from 'axios'; + +jest.mock( 'axios' ); +const mockedAxios = axios as jest.Mocked; + +declare global { + namespace NodeJS { + interface Global { + window: Window; + } + } +} + +const IBAN = 'DE12500105170648489890'; + +const errorSummaryItemIsFunctional = ( wrapper: VueWrapper, formElement: string, scrollElement: string ): boolean => { + const errorItemExists = wrapper.find( `.error-summary a[href="#${formElement}"]` ).exists(); + const formElementExists = wrapper.find( `#${formElement}` ).exists(); + const scrollElementExists = wrapper.find( `#${scrollElement}` ).exists(); + + return errorItemExists && formElementExists && scrollElementExists; +}; + +describe( 'DonationForm.vue (with receipt question field)', () => { + + beforeEach( () => { + global.window.scrollTo = jest.fn(); + jest.useFakeTimers(); + } ); + + afterEach( () => { + jest.clearAllMocks(); + document.getElementsByTagName( 'html' )[ 0 ].innerHTML = ''; + } ); + + const getWrapper = (): VueWrapper => { + const store = createStore(); + return mount( DonationForm, { + props: { + assetsPath: '', + paymentAmounts: [ 500, 1000, 2000 ], + paymentIntervals: [ 0, 1, 3, 6, 12 ], + paymentTypes: [ 'BEZ', 'PPL', 'UEB', 'BTC' ], + validateAddressUrl: 'https://example.com/address-check', + countries: countries, + trackingData: { bannerImpressionCount: 0, impressionCount: 0 }, + campaignValues: { campaign: 'nicholas', keyword: 'cage' }, + validateEmailUrl: '', + validateBankDataUrl: '', + validateLegacyBankDataUrl: '', + salutations: [ + { + label: 'Mr', + value: 'Mr', + display: 'Mr', + greetings: { + formal: 'Mr', + informal: 'Mr', + lastNameInformal: 'Mr', + }, + }, + { + label: 'Ms', + value: 'Ms', + display: 'Ms', + greetings: { + formal: 'Ms', + informal: 'Ms', + lastNameInformal: 'Ms', + }, + }, + ], + addressValidationPatterns: { postcode: '', country: null } as AddressValidation, + }, + global: { + plugins: [ store ], + provide: { + bankValidationResource: new FakeBankValidationResource(), + }, + components: { + FeatureToggle: createFeatureToggle( [ 'campaigns.address_pages.test_02' ] ), + }, + }, + attachTo: document.body, + } ); + }; + + it( 'handles the error summary when no receipt option was selected before submitting', async () => { + const wrapper = getWrapper(); + + await wrapper.find( '#donation-form' ).trigger( 'submit' ); + await nextTick(); + await nextTick(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'amount-500', 'payment-form-amount-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'paymentType-0', 'payment-form-type-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'salutation-0', 'salutation-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'first-name', 'first-name-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'last-name', 'last-name-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'email', 'email-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'donationReceipt-0', 'receipt-scroll-target' ) ).toBeTruthy(); + + await wrapper.find( 'input[name="amount"][value="500"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="paymentType"][value="PPL"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="salutation"][value="Mr"]' ).trigger( 'change' ); + + await wrapper.find( '#first-name' ).setValue( 'first-name' ); + await wrapper.find( '#first-name' ).trigger( 'blur' ); + + await wrapper.find( '#last-name' ).setValue( 'last-name' ); + await wrapper.find( '#last-name' ).trigger( 'blur' ); + + await wrapper.find( '#email' ).setValue( 'joe@dolan.com' ); + await wrapper.find( '#email' ).trigger( 'blur' ); + + await wrapper.find( 'input[name="donationReceipt"][value="false"]' ).trigger( 'change' ); + + await jest.runAllTimersAsync(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeFalsy(); + } ); + + it( 'handles the error summary when only receipt option yes was selected selected before submitting', async () => { + const wrapper = getWrapper(); + + await wrapper.find( 'input[name="donationReceipt"][value="true"]' ).trigger( 'change' ); + await wrapper.find( '#country' ).setValue( 'I am clearly not a country' ); + await wrapper.find( '#country' ).trigger( 'blur' ); + await jest.runAllTimersAsync(); + + await wrapper.find( '#donation-form' ).trigger( 'submit' ); + await nextTick(); + await nextTick(); + + expect( errorSummaryItemIsFunctional( wrapper, 'paymentType-0', 'payment-form-type-scroll-target' ) ).toBeTruthy(); + + // Make the IBAN field appear + await wrapper.find( 'input[name="paymentType"][value="BEZ"]' ).trigger( 'change' ); + await wrapper.find( '#donation-form' ).trigger( 'submit' ); + await nextTick(); + await nextTick(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'amount-500', 'payment-form-amount-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'account-number', 'account-number-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'salutation-0', 'salutation-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'first-name', 'first-name-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'last-name', 'last-name-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'email', 'email-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'addressType-0', 'address-type-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'street', 'street-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'post-code', 'post-code-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'city', 'city-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'country', 'country-scroll-target' ) ).toBeTruthy(); + + await wrapper.find( 'input[name="amount"][value="500"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="salutation"][value="Mr"]' ).trigger( 'change' ); + + await wrapper.find( '#account-number' ).setValue( IBAN ); + await wrapper.find( '#account-number' ).trigger( 'blur' ); + + await wrapper.find( '#first-name' ).setValue( 'first-name' ); + await wrapper.find( '#first-name' ).trigger( 'blur' ); + + await wrapper.find( '#last-name' ).setValue( 'last-name' ); + await wrapper.find( '#last-name' ).trigger( 'blur' ); + + await wrapper.find( 'input[name="addressTypeSelector"][value="0"]' ).trigger( 'change' ); + + await wrapper.find( '#street' ).setValue( 'street' ); + await wrapper.find( '#street' ).trigger( 'blur' ); + + await wrapper.find( '#post-code' ).setValue( '12345' ); + await wrapper.find( '#post-code' ).trigger( 'blur' ); + + await wrapper.find( '#city' ).setValue( 'city' ); + await wrapper.find( '#city' ).trigger( 'blur' ); + + await wrapper.find( '#country' ).setValue( countries[ 0 ].countryFullName ); + await wrapper.find( '#country' ).trigger( 'blur' ); + + await wrapper.find( '#email' ).setValue( 'joe@dolan.com' ); + await wrapper.find( '#email' ).trigger( 'blur' ); + + await jest.runAllTimersAsync(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeFalsy(); + } ); + + it( 'handles the error summary when person address type was selected selected before submitting', async () => { + const wrapper = getWrapper(); + + await wrapper.find( 'input[name="donationReceipt"][value="true"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="addressTypeSelector"][value="0"]' ).trigger( 'change' ); + await wrapper.find( '#country' ).setValue( 'I am clearly not a country' ); + await wrapper.find( '#country' ).trigger( 'blur' ); + await jest.runAllTimersAsync(); + + await wrapper.find( '#donation-form' ).trigger( 'submit' ); + await nextTick(); + await nextTick(); + + expect( errorSummaryItemIsFunctional( wrapper, 'paymentType-0', 'payment-form-type-scroll-target' ) ).toBeTruthy(); + + // Make the IBAN field appear + await wrapper.find( 'input[name="paymentType"][value="BEZ"]' ).trigger( 'change' ); + await wrapper.find( '#donation-form' ).trigger( 'submit' ); + await nextTick(); + await nextTick(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'amount-500', 'payment-form-amount-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'account-number', 'account-number-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'salutation-0', 'salutation-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'first-name', 'first-name-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'last-name', 'last-name-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'email', 'email-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'street', 'street-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'post-code', 'post-code-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'city', 'city-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'country', 'country-scroll-target' ) ).toBeTruthy(); + + await wrapper.find( 'input[name="amount"][value="500"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="salutation"][value="Mr"]' ).trigger( 'change' ); + + await wrapper.find( '#account-number' ).setValue( IBAN ); + await wrapper.find( '#account-number' ).trigger( 'blur' ); + + await wrapper.find( '#first-name' ).setValue( 'first-name' ); + await wrapper.find( '#first-name' ).trigger( 'blur' ); + + await wrapper.find( '#last-name' ).setValue( 'last-name' ); + await wrapper.find( '#last-name' ).trigger( 'blur' ); + + await wrapper.find( '#street' ).setValue( 'street' ); + await wrapper.find( '#street' ).trigger( 'blur' ); + + await wrapper.find( '#post-code' ).setValue( '12345' ); + await wrapper.find( '#post-code' ).trigger( 'blur' ); + + await wrapper.find( '#city' ).setValue( 'city' ); + await wrapper.find( '#city' ).trigger( 'blur' ); + + await wrapper.find( '#country' ).setValue( countries[ 0 ].countryFullName ); + await wrapper.find( '#country' ).trigger( 'blur' ); + + await wrapper.find( '#email' ).setValue( 'joe@dolan.com' ); + await wrapper.find( '#email' ).trigger( 'blur' ); + + await jest.runAllTimersAsync(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeFalsy(); + } ); + + it( 'handles the error summary when company address type was selected before submitting', async () => { + const wrapper = getWrapper(); + + await wrapper.find( 'input[name="donationReceipt"][value="true"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="addressTypeSelector"][value="2"]' ).trigger( 'change' ); + await nextTick(); + + await wrapper.find( '#country' ).setValue( 'I am clearly not a country' ); + await wrapper.find( '#country' ).trigger( 'blur' ); + await jest.runAllTimersAsync(); + + await wrapper.find( '#donation-form' ).trigger( 'submit' ); + await nextTick(); + await nextTick(); + + expect( errorSummaryItemIsFunctional( wrapper, 'paymentType-0', 'payment-form-type-scroll-target' ) ).toBeTruthy(); + + // Make the IBAN field appear + await wrapper.find( 'input[name="paymentType"][value="BEZ"]' ).trigger( 'change' ); + await wrapper.find( '#donation-form' ).trigger( 'submit' ); + await nextTick(); + await nextTick(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'amount-500', 'payment-form-amount-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'account-number', 'account-number-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'salutation-0', 'salutation-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'first-name', 'first-name-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'last-name', 'last-name-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'email', 'email-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'company-name', 'company-name-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'street', 'street-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'post-code', 'post-code-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'city', 'city-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'country', 'country-scroll-target' ) ).toBeTruthy(); + + await wrapper.find( 'input[name="amount"][value="500"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="salutation"][value="Mr"]' ).trigger( 'change' ); + + await wrapper.find( '#account-number' ).setValue( IBAN ); + await wrapper.find( '#account-number' ).trigger( 'blur' ); + + await wrapper.find( '#first-name' ).setValue( 'first-name' ); + await wrapper.find( '#first-name' ).trigger( 'blur' ); + + await wrapper.find( '#last-name' ).setValue( 'last-name' ); + await wrapper.find( '#last-name' ).trigger( 'blur' ); + + await wrapper.find( '#company-name' ).setValue( 'company-name' ); + await wrapper.find( '#company-name' ).trigger( 'blur' ); + + await wrapper.find( '#street' ).setValue( 'street' ); + await wrapper.find( '#street' ).trigger( 'blur' ); + + await wrapper.find( '#post-code' ).setValue( '12345' ); + await wrapper.find( '#post-code' ).trigger( 'blur' ); + + await wrapper.find( '#city' ).setValue( 'city' ); + await wrapper.find( '#city' ).trigger( 'blur' ); + + await wrapper.find( '#country' ).setValue( countries[ 0 ].countryFullName ); + await wrapper.find( '#country' ).trigger( 'blur' ); + + await wrapper.find( '#email' ).setValue( 'joe@dolan.com' ); + await wrapper.find( '#email' ).trigger( 'blur' ); + + await jest.runAllTimersAsync(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeFalsy(); + } ); + + it( 'submits the form for a person', async () => { + mockedAxios.post.mockResolvedValue( { data: { status: 'OK' } } ); + const wrapper = getWrapper(); + + const submitForm = wrapper.find( '#donation-form-submit-values' ); + submitForm.element.submit = jest.fn(); + + await wrapper.find( 'input[name="amount"][value="500"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="paymentType"][value="BEZ"]' ).trigger( 'change' ); + + await wrapper.find( '#account-number' ).setValue( IBAN ); + await wrapper.find( '#account-number' ).trigger( 'blur' ); + + await wrapper.find( 'input[name="salutation"][value="Mr"]' ).trigger( 'change' ); + + await wrapper.find( '#first-name' ).setValue( 'first-name' ); + await wrapper.find( '#first-name' ).trigger( 'blur' ); + + await wrapper.find( '#last-name' ).setValue( 'last-name' ); + await wrapper.find( '#last-name' ).trigger( 'blur' ); + + await wrapper.find( '#email' ).setValue( 'joe@dolan.com' ); + await wrapper.find( '#email' ).trigger( 'blur' ); + + await wrapper.find( 'input[name="donationReceipt"][value="true"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="addressTypeSelector"][value="0"]' ).trigger( 'change' ); + + await wrapper.find( '#street' ).setValue( 'street' ); + await wrapper.find( '#street' ).trigger( 'blur' ); + + await wrapper.find( '#post-code' ).setValue( '12345' ); + await wrapper.find( '#post-code' ).trigger( 'blur' ); + + await wrapper.find( '#city' ).setValue( 'city' ); + await wrapper.find( '#city' ).trigger( 'blur' ); + + await jest.runAllTimersAsync(); + + await wrapper.find( '#country' ).setValue( countries[ 0 ].countryFullName ); + await wrapper.find( '#country' ).trigger( 'blur' ); + + await wrapper.find( '#donation-form' ).trigger( 'submit' ); + + await jest.runAllTimersAsync(); + await flushPromises(); + + expect( submitForm.element.submit ).toHaveBeenCalled(); + } ); + + it( 'submits the form for a company', async () => { + mockedAxios.post.mockResolvedValue( { data: { status: 'OK' } } ); + const wrapper = getWrapper(); + + const submitForm = wrapper.find( '#donation-form-submit-values' ); + submitForm.element.submit = jest.fn(); + + await wrapper.find( 'input[name="amount"][value="500"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="paymentType"][value="BEZ"]' ).trigger( 'change' ); + + await wrapper.find( '#account-number' ).setValue( IBAN ); + await wrapper.find( '#account-number' ).trigger( 'blur' ); + + await wrapper.find( 'input[name="salutation"][value="Mr"]' ).trigger( 'change' ); + + await wrapper.find( '#first-name' ).setValue( 'first-name' ); + await wrapper.find( '#first-name' ).trigger( 'blur' ); + + await wrapper.find( '#last-name' ).setValue( 'last-name' ); + await wrapper.find( '#last-name' ).trigger( 'blur' ); + + await wrapper.find( '#email' ).setValue( 'joe@dolan.com' ); + await wrapper.find( '#email' ).trigger( 'blur' ); + + await wrapper.find( 'input[name="donationReceipt"][value="true"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="addressTypeSelector"][value="2"]' ).trigger( 'change' ); + + await wrapper.find( '#company-name' ).setValue( 'company-name' ); + await wrapper.find( '#company-name' ).trigger( 'blur' ); + + await wrapper.find( '#street' ).setValue( 'street' ); + await wrapper.find( '#street' ).trigger( 'blur' ); + + await wrapper.find( '#post-code' ).setValue( '12345' ); + await wrapper.find( '#post-code' ).trigger( 'blur' ); + + await wrapper.find( '#city' ).setValue( 'city' ); + await wrapper.find( '#city' ).trigger( 'blur' ); + + await jest.runAllTimersAsync(); + + await wrapper.find( '#country' ).setValue( countries[ 0 ].countryFullName ); + await wrapper.find( '#country' ).trigger( 'blur' ); + + await wrapper.find( '#donation-form' ).trigger( 'submit' ); + + await jest.runAllTimersAsync(); + await flushPromises(); + + expect( submitForm.element.submit ).toHaveBeenCalled(); + } ); + + it( 'submits the form for anonymous', async () => { + mockedAxios.post.mockResolvedValue( { data: { status: 'OK' } } ); + const wrapper = getWrapper(); + + const submitForm = wrapper.find( '#donation-form-submit-values' ); + submitForm.element.submit = jest.fn(); + + await wrapper.find( 'input[name="amount"][value="500"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="paymentType"][value="BEZ"]' ).trigger( 'change' ); + + await wrapper.find( '#account-number' ).setValue( IBAN ); + await wrapper.find( '#account-number' ).trigger( 'blur' ); + + await wrapper.find( 'input[name="salutation"][value="Mr"]' ).trigger( 'change' ); + + await wrapper.find( '#first-name' ).setValue( 'first-name' ); + await wrapper.find( '#first-name' ).trigger( 'blur' ); + + await wrapper.find( '#last-name' ).setValue( 'last-name' ); + await wrapper.find( '#last-name' ).trigger( 'blur' ); + + await wrapper.find( '#email' ).setValue( 'joe@dolan.com' ); + await wrapper.find( '#email' ).trigger( 'blur' ); + + await wrapper.find( 'input[name="donationReceipt"][value="false"]' ).trigger( 'change' ); + + await wrapper.find( '#donation-form' ).trigger( 'submit' ); + + await jest.runAllTimersAsync(); + await flushPromises(); + + expect( submitForm.element.submit ).toHaveBeenCalled(); + } ); +} ); diff --git a/tests/unit/components/pages/donation_form/DonationFormReceiptAlternateOrder.spec.ts b/tests/unit/components/pages/donation_form/DonationFormReceiptAlternateOrder.spec.ts new file mode 100644 index 000000000..1f099a457 --- /dev/null +++ b/tests/unit/components/pages/donation_form/DonationFormReceiptAlternateOrder.spec.ts @@ -0,0 +1,469 @@ +import { flushPromises, mount, VueWrapper } from '@vue/test-utils'; +import DonationForm from '@src/components/pages/DonationForm.vue'; +import countries from '@test/data/countries'; +import { AddressValidation } from '@src/view_models/Validation'; +import { createFeatureToggle } from '@src/util/createFeatureToggle'; +import { createStore } from '@src/store/donation_store'; +import { FakeBankValidationResource } from '@test/unit/TestDoubles/FakeBankValidationResource'; +import { nextTick } from 'vue'; +import axios from 'axios'; + +jest.mock( 'axios' ); +const mockedAxios = axios as jest.Mocked; + +declare global { + namespace NodeJS { + interface Global { + window: Window; + } + } +} + +const IBAN = 'DE12500105170648489890'; + +const errorSummaryItemIsFunctional = ( wrapper: VueWrapper, formElement: string, scrollElement: string ): boolean => { + const errorItemExists = wrapper.find( `.error-summary a[href="#${formElement}"]` ).exists(); + const formElementExists = wrapper.find( `#${formElement}` ).exists(); + const scrollElementExists = wrapper.find( `#${scrollElement}` ).exists(); + + return errorItemExists && formElementExists && scrollElementExists; +}; + +describe( 'DonationForm.vue (with receipt question field and alternate order)', () => { + + beforeEach( () => { + global.window.scrollTo = jest.fn(); + jest.useFakeTimers(); + } ); + + afterEach( () => { + jest.clearAllMocks(); + document.getElementsByTagName( 'html' )[ 0 ].innerHTML = ''; + } ); + + const getWrapper = (): VueWrapper => { + const store = createStore(); + return mount( DonationForm, { + props: { + assetsPath: '', + paymentAmounts: [ 500, 1000, 2000 ], + paymentIntervals: [ 0, 1, 3, 6, 12 ], + paymentTypes: [ 'BEZ', 'PPL', 'UEB', 'BTC' ], + validateAddressUrl: 'https://example.com/address-check', + countries: countries, + trackingData: { bannerImpressionCount: 0, impressionCount: 0 }, + campaignValues: { campaign: 'nicholas', keyword: 'cage' }, + validateEmailUrl: '', + validateBankDataUrl: '', + validateLegacyBankDataUrl: '', + salutations: [ + { + label: 'Mr', + value: 'Mr', + display: 'Mr', + greetings: { + formal: 'Mr', + informal: 'Mr', + lastNameInformal: 'Mr', + }, + }, + { + label: 'Ms', + value: 'Ms', + display: 'Ms', + greetings: { + formal: 'Ms', + informal: 'Ms', + lastNameInformal: 'Ms', + }, + }, + ], + addressValidationPatterns: { postcode: '', country: null } as AddressValidation, + }, + global: { + plugins: [ store ], + provide: { + bankValidationResource: new FakeBankValidationResource(), + }, + components: { + FeatureToggle: createFeatureToggle( [ 'campaigns.address_pages.test_02', 'campaigns.address_field_order.new_order' ] ), + }, + }, + attachTo: document.body, + } ); + }; + + it( 'handles the error summary when no receipt option was selected before submitting', async () => { + const wrapper = getWrapper(); + + await wrapper.find( '#donation-form' ).trigger( 'submit' ); + await nextTick(); + await nextTick(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'amount-500', 'payment-form-amount-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'paymentType-0', 'payment-form-type-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'salutation-0', 'salutation-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'first-name', 'first-name-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'last-name', 'last-name-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'email', 'email-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'donationReceipt-0', 'receipt-scroll-target' ) ).toBeTruthy(); + + await wrapper.find( 'input[name="amount"][value="500"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="paymentType"][value="PPL"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="salutation"][value="Mr"]' ).trigger( 'change' ); + + await wrapper.find( '#first-name' ).setValue( 'first-name' ); + await wrapper.find( '#first-name' ).trigger( 'blur' ); + + await wrapper.find( '#last-name' ).setValue( 'last-name' ); + await wrapper.find( '#last-name' ).trigger( 'blur' ); + + await wrapper.find( '#email' ).setValue( 'joe@dolan.com' ); + await wrapper.find( '#email' ).trigger( 'blur' ); + + await wrapper.find( 'input[name="donationReceipt"][value="false"]' ).trigger( 'change' ); + + await jest.runAllTimersAsync(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeFalsy(); + } ); + + it( 'handles the error summary when only receipt option yes was selected before submitting', async () => { + const wrapper = getWrapper(); + + await wrapper.find( 'input[name="donationReceipt"][value="true"]' ).trigger( 'change' ); + await wrapper.find( '#country' ).setValue( 'I am clearly not a country' ); + await wrapper.find( '#country' ).trigger( 'blur' ); + await jest.runAllTimersAsync(); + + await wrapper.find( '#donation-form' ).trigger( 'submit' ); + await nextTick(); + await nextTick(); + + expect( errorSummaryItemIsFunctional( wrapper, 'paymentType-0', 'payment-form-type-scroll-target' ) ).toBeTruthy(); + + // Make the IBAN field appear + await wrapper.find( 'input[name="paymentType"][value="BEZ"]' ).trigger( 'change' ); + await wrapper.find( '#donation-form' ).trigger( 'submit' ); + await nextTick(); + await nextTick(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'amount-500', 'payment-form-amount-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'account-number', 'account-number-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'salutation-0', 'salutation-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'first-name', 'first-name-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'last-name', 'last-name-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'email', 'email-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'addressType-0', 'address-type-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'street', 'street-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'post-code', 'post-code-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'city', 'city-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'country', 'country-scroll-target' ) ).toBeTruthy(); + + await wrapper.find( 'input[name="amount"][value="500"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="salutation"][value="Mr"]' ).trigger( 'change' ); + + await wrapper.find( '#account-number' ).setValue( IBAN ); + await wrapper.find( '#account-number' ).trigger( 'blur' ); + + await wrapper.find( '#first-name' ).setValue( 'first-name' ); + await wrapper.find( '#first-name' ).trigger( 'blur' ); + + await wrapper.find( '#last-name' ).setValue( 'last-name' ); + await wrapper.find( '#last-name' ).trigger( 'blur' ); + + await wrapper.find( 'input[name="addressTypeSelector"][value="0"]' ).trigger( 'change' ); + + await wrapper.find( '#street' ).setValue( 'street' ); + await wrapper.find( '#street' ).trigger( 'blur' ); + + await wrapper.find( '#post-code' ).setValue( '12345' ); + await wrapper.find( '#post-code' ).trigger( 'blur' ); + + await wrapper.find( '#city' ).setValue( 'city' ); + await wrapper.find( '#city' ).trigger( 'blur' ); + + await wrapper.find( '#country' ).setValue( countries[ 0 ].countryFullName ); + await wrapper.find( '#country' ).trigger( 'blur' ); + + await wrapper.find( '#email' ).setValue( 'joe@dolan.com' ); + await wrapper.find( '#email' ).trigger( 'blur' ); + + await jest.runAllTimersAsync(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeFalsy(); + } ); + + it( 'handles the error summary when person address type was selected before submitting', async () => { + const wrapper = getWrapper(); + + await wrapper.find( 'input[name="donationReceipt"][value="true"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="addressTypeSelector"][value="0"]' ).trigger( 'change' ); + await wrapper.find( '#country' ).setValue( 'I am clearly not a country' ); + await wrapper.find( '#country' ).trigger( 'blur' ); + await jest.runAllTimersAsync(); + + await wrapper.find( '#donation-form' ).trigger( 'submit' ); + await nextTick(); + await nextTick(); + + expect( errorSummaryItemIsFunctional( wrapper, 'paymentType-0', 'payment-form-type-scroll-target' ) ).toBeTruthy(); + + // Make the IBAN field appear + await wrapper.find( 'input[name="paymentType"][value="BEZ"]' ).trigger( 'change' ); + await wrapper.find( '#donation-form' ).trigger( 'submit' ); + await nextTick(); + await nextTick(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'amount-500', 'payment-form-amount-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'account-number', 'account-number-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'salutation-0', 'salutation-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'first-name', 'first-name-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'last-name', 'last-name-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'email', 'email-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'street', 'street-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'post-code', 'post-code-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'city', 'city-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'country', 'country-scroll-target' ) ).toBeTruthy(); + + await wrapper.find( 'input[name="amount"][value="500"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="salutation"][value="Mr"]' ).trigger( 'change' ); + + await wrapper.find( '#account-number' ).setValue( IBAN ); + await wrapper.find( '#account-number' ).trigger( 'blur' ); + + await wrapper.find( '#first-name' ).setValue( 'first-name' ); + await wrapper.find( '#first-name' ).trigger( 'blur' ); + + await wrapper.find( '#last-name' ).setValue( 'last-name' ); + await wrapper.find( '#last-name' ).trigger( 'blur' ); + + await wrapper.find( '#street' ).setValue( 'street' ); + await wrapper.find( '#street' ).trigger( 'blur' ); + + await wrapper.find( '#post-code' ).setValue( '12345' ); + await wrapper.find( '#post-code' ).trigger( 'blur' ); + + await wrapper.find( '#city' ).setValue( 'city' ); + await wrapper.find( '#city' ).trigger( 'blur' ); + + await wrapper.find( '#country' ).setValue( countries[ 0 ].countryFullName ); + await wrapper.find( '#country' ).trigger( 'blur' ); + + await wrapper.find( '#email' ).setValue( 'joe@dolan.com' ); + await wrapper.find( '#email' ).trigger( 'blur' ); + + await jest.runAllTimersAsync(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeFalsy(); + } ); + + it( 'handles the error summary when company address type was selected before submitting', async () => { + const wrapper = getWrapper(); + + await wrapper.find( 'input[name="donationReceipt"][value="true"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="addressTypeSelector"][value="2"]' ).trigger( 'change' ); + await nextTick(); + + await wrapper.find( '#country' ).setValue( 'I am clearly not a country' ); + await wrapper.find( '#country' ).trigger( 'blur' ); + await jest.runAllTimersAsync(); + + await wrapper.find( '#donation-form' ).trigger( 'submit' ); + await nextTick(); + await nextTick(); + + expect( errorSummaryItemIsFunctional( wrapper, 'paymentType-0', 'payment-form-type-scroll-target' ) ).toBeTruthy(); + + // Make the IBAN field appear + await wrapper.find( 'input[name="paymentType"][value="BEZ"]' ).trigger( 'change' ); + await wrapper.find( '#donation-form' ).trigger( 'submit' ); + await nextTick(); + await nextTick(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'amount-500', 'payment-form-amount-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'account-number', 'account-number-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'salutation-0', 'salutation-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'first-name', 'first-name-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'last-name', 'last-name-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'email', 'email-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'company-name', 'company-name-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'street', 'street-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'post-code', 'post-code-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'city', 'city-scroll-target' ) ).toBeTruthy(); + expect( errorSummaryItemIsFunctional( wrapper, 'country', 'country-scroll-target' ) ).toBeTruthy(); + + await wrapper.find( 'input[name="amount"][value="500"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="salutation"][value="Mr"]' ).trigger( 'change' ); + + await wrapper.find( '#account-number' ).setValue( IBAN ); + await wrapper.find( '#account-number' ).trigger( 'blur' ); + + await wrapper.find( '#first-name' ).setValue( 'first-name' ); + await wrapper.find( '#first-name' ).trigger( 'blur' ); + + await wrapper.find( '#last-name' ).setValue( 'last-name' ); + await wrapper.find( '#last-name' ).trigger( 'blur' ); + + await wrapper.find( '#company-name' ).setValue( 'company-name' ); + await wrapper.find( '#company-name' ).trigger( 'blur' ); + + await wrapper.find( '#street' ).setValue( 'street' ); + await wrapper.find( '#street' ).trigger( 'blur' ); + + await wrapper.find( '#post-code' ).setValue( '12345' ); + await wrapper.find( '#post-code' ).trigger( 'blur' ); + + await wrapper.find( '#city' ).setValue( 'city' ); + await wrapper.find( '#city' ).trigger( 'blur' ); + + await wrapper.find( '#country' ).setValue( countries[ 0 ].countryFullName ); + await wrapper.find( '#country' ).trigger( 'blur' ); + + await wrapper.find( '#email' ).setValue( 'joe@dolan.com' ); + await wrapper.find( '#email' ).trigger( 'blur' ); + + await jest.runAllTimersAsync(); + + expect( wrapper.find( '.error-summary' ).exists() ).toBeFalsy(); + } ); + + it( 'submits the form for a person', async () => { + mockedAxios.post.mockResolvedValue( { data: { status: 'OK' } } ); + const wrapper = getWrapper(); + + const submitForm = wrapper.find( '#donation-form-submit-values' ); + submitForm.element.submit = jest.fn(); + + await wrapper.find( 'input[name="amount"][value="500"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="paymentType"][value="BEZ"]' ).trigger( 'change' ); + + await wrapper.find( '#account-number' ).setValue( IBAN ); + await wrapper.find( '#account-number' ).trigger( 'blur' ); + + await wrapper.find( 'input[name="salutation"][value="Mr"]' ).trigger( 'change' ); + + await wrapper.find( '#first-name' ).setValue( 'first-name' ); + await wrapper.find( '#first-name' ).trigger( 'blur' ); + + await wrapper.find( '#last-name' ).setValue( 'last-name' ); + await wrapper.find( '#last-name' ).trigger( 'blur' ); + + await wrapper.find( '#email' ).setValue( 'joe@dolan.com' ); + await wrapper.find( '#email' ).trigger( 'blur' ); + + await wrapper.find( 'input[name="donationReceipt"][value="true"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="addressTypeSelector"][value="0"]' ).trigger( 'change' ); + + await wrapper.find( '#street' ).setValue( 'street' ); + await wrapper.find( '#street' ).trigger( 'blur' ); + + await wrapper.find( '#post-code' ).setValue( '12345' ); + await wrapper.find( '#post-code' ).trigger( 'blur' ); + + await wrapper.find( '#city' ).setValue( 'city' ); + await wrapper.find( '#city' ).trigger( 'blur' ); + + await jest.runAllTimersAsync(); + + await wrapper.find( '#country' ).setValue( countries[ 0 ].countryFullName ); + await wrapper.find( '#country' ).trigger( 'blur' ); + + await wrapper.find( '#donation-form' ).trigger( 'submit' ); + + await jest.runAllTimersAsync(); + await flushPromises(); + + expect( submitForm.element.submit ).toHaveBeenCalled(); + } ); + + it( 'submits the form for a company', async () => { + mockedAxios.post.mockResolvedValue( { data: { status: 'OK' } } ); + const wrapper = getWrapper(); + + const submitForm = wrapper.find( '#donation-form-submit-values' ); + submitForm.element.submit = jest.fn(); + + await wrapper.find( 'input[name="amount"][value="500"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="paymentType"][value="BEZ"]' ).trigger( 'change' ); + + await wrapper.find( '#account-number' ).setValue( IBAN ); + await wrapper.find( '#account-number' ).trigger( 'blur' ); + + await wrapper.find( 'input[name="salutation"][value="Mr"]' ).trigger( 'change' ); + + await wrapper.find( '#first-name' ).setValue( 'first-name' ); + await wrapper.find( '#first-name' ).trigger( 'blur' ); + + await wrapper.find( '#last-name' ).setValue( 'last-name' ); + await wrapper.find( '#last-name' ).trigger( 'blur' ); + + await wrapper.find( '#email' ).setValue( 'joe@dolan.com' ); + await wrapper.find( '#email' ).trigger( 'blur' ); + + await wrapper.find( 'input[name="donationReceipt"][value="true"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="addressTypeSelector"][value="2"]' ).trigger( 'change' ); + + await wrapper.find( '#company-name' ).setValue( 'company-name' ); + await wrapper.find( '#company-name' ).trigger( 'blur' ); + + await wrapper.find( '#street' ).setValue( 'street' ); + await wrapper.find( '#street' ).trigger( 'blur' ); + + await wrapper.find( '#post-code' ).setValue( '12345' ); + await wrapper.find( '#post-code' ).trigger( 'blur' ); + + await wrapper.find( '#city' ).setValue( 'city' ); + await wrapper.find( '#city' ).trigger( 'blur' ); + + await jest.runAllTimersAsync(); + + await wrapper.find( '#country' ).setValue( countries[ 0 ].countryFullName ); + await wrapper.find( '#country' ).trigger( 'blur' ); + + await wrapper.find( '#donation-form' ).trigger( 'submit' ); + + await jest.runAllTimersAsync(); + await flushPromises(); + + expect( submitForm.element.submit ).toHaveBeenCalled(); + } ); + + it( 'submits the form for anonymous', async () => { + mockedAxios.post.mockResolvedValue( { data: { status: 'OK' } } ); + const wrapper = getWrapper(); + + const submitForm = wrapper.find( '#donation-form-submit-values' ); + submitForm.element.submit = jest.fn(); + + await wrapper.find( 'input[name="amount"][value="500"]' ).trigger( 'change' ); + await wrapper.find( 'input[name="paymentType"][value="BEZ"]' ).trigger( 'change' ); + + await wrapper.find( '#account-number' ).setValue( IBAN ); + await wrapper.find( '#account-number' ).trigger( 'blur' ); + + await wrapper.find( 'input[name="salutation"][value="Mr"]' ).trigger( 'change' ); + + await wrapper.find( '#first-name' ).setValue( 'first-name' ); + await wrapper.find( '#first-name' ).trigger( 'blur' ); + + await wrapper.find( '#last-name' ).setValue( 'last-name' ); + await wrapper.find( '#last-name' ).trigger( 'blur' ); + + await wrapper.find( '#email' ).setValue( 'joe@dolan.com' ); + await wrapper.find( '#email' ).trigger( 'blur' ); + + await wrapper.find( 'input[name="donationReceipt"][value="false"]' ).trigger( 'change' ); + + await wrapper.find( '#donation-form' ).trigger( 'submit' ); + + await jest.runAllTimersAsync(); + await flushPromises(); + + expect( submitForm.element.submit ).toHaveBeenCalled(); + } ); +} ); diff --git a/tests/unit/components/pages/donation_form/single_page_form/PersonalDataSection.spec.ts b/tests/unit/components/pages/donation_form/single_page_form/PersonalDataSection.spec.ts index eaa248844..809f299ec 100644 --- a/tests/unit/components/pages/donation_form/single_page_form/PersonalDataSection.spec.ts +++ b/tests/unit/components/pages/donation_form/single_page_form/PersonalDataSection.spec.ts @@ -1,6 +1,4 @@ -import { flushPromises, mount, VueWrapper } from '@vue/test-utils'; - -import axios from 'axios'; +import { mount, VueWrapper } from '@vue/test-utils'; import { createStore } from '@src/store/donation_store'; import { action } from '@src/store/util'; import { AddressTypeModel } from '@src/view_models/AddressTypeModel'; @@ -11,7 +9,6 @@ import { CampaignValues } from '@src/view_models/CampaignValues'; import { AddressValidation } from '@src/view_models/Validation'; import { nextTick } from 'vue'; import AddressTypeBasic from '@src/components/pages/donation_form/AddressTypeBasic.vue'; -import { Validity } from '@src/view_models/Validity'; import { Salutation } from '@src/view_models/Salutation'; import PersonalDataSection from '@src/components/pages/donation_form/singlePageFormSections/PersonalDataSection.vue'; import { FakeBankValidationResource } from '@test/unit/TestDoubles/FakeBankValidationResource'; @@ -37,9 +34,6 @@ const salutations: Salutation[] = [ }, ]; -jest.mock( 'axios' ); -const mockedAxios = axios as jest.Mocked; - describe( 'PersonalDataSection.vue', () => { const getWrapper = ( store: Store = createStore() ): { wrapper: VueWrapper, store: Store } => { const wrapper = mount( PersonalDataSection, { @@ -130,137 +124,6 @@ describe( 'PersonalDataSection.vue', () => { expect( scrollElement.scrollIntoView ).toHaveBeenCalledWith( { behavior: 'smooth' } ); } ); - it( 'shows and hides the error summary', async () => { - jest.useFakeTimers(); - - const { wrapper, store } = getWrapper(); - - await setPaymentTypeAndInitializeOtherPaymentValues( store, 'UEB' ); - - await wrapper.find( '#submit-btn' ).trigger( 'click' ); - await nextTick(); - await nextTick(); - - expect( wrapper.find( '.error-summary' ).exists() ).toBeTruthy(); - - await wrapper.find( '#addressType-0' ).trigger( 'change' ); - await wrapper.find( '#person-salutation-0' ).trigger( 'change' ); - - await wrapper.find( '#person-first-name' ).setValue( 'first-name' ); - await wrapper.find( '#person-first-name' ).trigger( 'blur' ); - - await wrapper.find( '#person-last-name' ).setValue( 'last-name' ); - await wrapper.find( '#person-last-name' ).trigger( 'blur' ); - - await wrapper.find( '#person-street' ).setValue( 'street' ); - await wrapper.find( '#person-street' ).trigger( 'blur' ); - - await wrapper.find( '#person-post-code' ).setValue( 'post-code' ); - await wrapper.find( '#person-post-code' ).trigger( 'blur' ); - - await wrapper.find( '#person-city' ).setValue( 'city' ); - await wrapper.find( '#person-city' ).trigger( 'blur' ); - - await wrapper.find( '#person-country' ).setValue( 'country' ); - await wrapper.find( '#person-country' ).trigger( 'blur' ); - - await wrapper.find( '#person-email' ).setValue( 'joe@dolan.com' ); - await wrapper.find( '#person-email' ).trigger( 'blur' ); - - await jest.runAllTimersAsync(); - - expect( wrapper.find( '.error-summary' ).exists() ).toBeFalsy(); - - jest.clearAllMocks(); - } ); - - it( 'shows and hides the error summary when payment data is invalid', async () => { - jest.useFakeTimers(); - - const { wrapper, store } = getWrapper(); - - await setPaymentTypeAndInitializeOtherPaymentValues( store, 'BEZ' ); - - await wrapper.find( '#submit-btn' ).trigger( 'click' ); - await nextTick(); - await nextTick(); - - expect( wrapper.find( '.error-summary' ).exists() ).toBeTruthy(); - - await wrapper.find( '#addressType-0' ).trigger( 'change' ); - await wrapper.find( '#person-salutation-0' ).trigger( 'change' ); - - await wrapper.find( '#person-first-name' ).setValue( 'first-name' ); - await wrapper.find( '#person-first-name' ).trigger( 'blur' ); - - await wrapper.find( '#person-last-name' ).setValue( 'last-name' ); - await wrapper.find( '#person-last-name' ).trigger( 'blur' ); - - await wrapper.find( '#person-street' ).setValue( 'street' ); - await wrapper.find( '#person-street' ).trigger( 'blur' ); - - await wrapper.find( '#person-post-code' ).setValue( 'post-code' ); - await wrapper.find( '#person-post-code' ).trigger( 'blur' ); - - await wrapper.find( '#person-city' ).setValue( 'city' ); - await wrapper.find( '#person-city' ).trigger( 'blur' ); - - await jest.runAllTimersAsync(); - - await wrapper.find( '#person-country' ).setValue( 'country' ); - await wrapper.find( '#person-country' ).trigger( 'blur' ); - - await wrapper.find( '#person-email' ).setValue( 'joe@dolan.com' ); - await wrapper.find( '#person-email' ).trigger( 'blur' ); - - expect( wrapper.find( '.error-summary' ).exists() ).toBeTruthy(); - - await wrapper.find( '#account-number' ).setValue( 'DE12500105170648489890' ); - await wrapper.find( '#account-number' ).trigger( 'blur' ); - - await flushPromises(); - - expect( wrapper.find( '.error-summary' ).exists() ).toBeFalsy(); - - jest.clearAllMocks(); - } ); - - test.each( [ - [ '', 10 ], - [ '#addressType-0', 9 ], - [ '#addressType-1', 7 ], - ] )( 'focuses inputs on error summary clicks', async ( addressTypeSelector: string, numberOfErrors: number ) => { - jest.useFakeTimers(); - - const { wrapper, store } = getWrapper(); - - await setPaymentTypeAndInitializeOtherPaymentValues( store, 'BEZ' ); - - if ( addressTypeSelector !== '' ) { - await wrapper.find( addressTypeSelector ).trigger( 'change' ); - } - - await wrapper.find( '#person-country' ).setValue( 'I am clearly not a country' ); - await wrapper.find( '#person-country' ).trigger( 'blur' ); - - await jest.runAllTimersAsync(); - - await wrapper.find( '#submit-btn' ).trigger( 'click' ); - await nextTick(); - await nextTick(); - - const errorLinks = wrapper.findAll( '.error-summary-list a' ); - - expect( errorLinks.length ).toStrictEqual( numberOfErrors ); - - errorLinks.forEach( x => { - expect( wrapper.find( x.attributes( 'href' ) ).exists() ).toBeTruthy(); - expect( wrapper.find( '#' + x.attributes( 'data-scroll-element' ) ).exists() ).toBeTruthy(); - } ); - - jest.clearAllMocks(); - } ); - it( 'updates full selected', async () => { const { wrapper } = getWrapper(); @@ -279,38 +142,4 @@ describe( 'PersonalDataSection.vue', () => { expect( store.dispatch ).toHaveBeenCalledWith( action( 'payment', 'markEmptyValuesAsInvalid' ) ); } ); - - it( 'submits the form', async () => { - const store = createStore(); - await setPaymentTypeAndInitializeOtherPaymentValues( store, 'UEB' ); - await store.dispatch( action( 'address', 'initializeAddress' ), { - addressType: AddressTypeModel.ANON, - newsletter: true, - receipt: true, - fields: [ - { name: 'salutation', value: 'Mr', validity: Validity.RESTORED }, - { name: 'title', value: 'Dr', validity: Validity.RESTORED }, - { name: 'firstName', value: 'value', validity: Validity.RESTORED }, - { name: 'lastName', value: 'value', validity: Validity.RESTORED }, - { name: 'street', value: 'value', validity: Validity.RESTORED }, - { name: 'postcode', value: '12345', validity: Validity.RESTORED }, - { name: 'city', value: 'value', validity: Validity.RESTORED }, - { name: 'country', value: 'value', validity: Validity.RESTORED }, - { name: 'email', value: 'value@gmail.com', validity: Validity.RESTORED }, - { name: 'companyName', value: 'value', validity: Validity.RESTORED }, - ], - } ); - - mockedAxios.post.mockResolvedValue( { data: { status: 'OK' } } ); - const { wrapper } = getWrapper( store ); - - const submitForm = wrapper.find( '#submit-form' ); - submitForm.element.submit = jest.fn(); - - await wrapper.find( '#submit-btn' ).trigger( 'click' ); - await flushPromises(); - - expect( submitForm.element.submit ).toHaveBeenCalled(); - } ); - } ); diff --git a/tests/unit/components/pages/donation_form/single_page_form/PersonalDataSectionDonationReceipt.spec.ts b/tests/unit/components/pages/donation_form/single_page_form/PersonalDataSectionDonationReceipt.spec.ts index f94c61e60..625ce312a 100644 --- a/tests/unit/components/pages/donation_form/single_page_form/PersonalDataSectionDonationReceipt.spec.ts +++ b/tests/unit/components/pages/donation_form/single_page_form/PersonalDataSectionDonationReceipt.spec.ts @@ -1,16 +1,11 @@ -import { flushPromises, mount, VueWrapper } from '@vue/test-utils'; - -import axios from 'axios'; +import { mount, VueWrapper } from '@vue/test-utils'; import { createStore } from '@src/store/donation_store'; import { action } from '@src/store/util'; -import { AddressTypeModel } from '@src/view_models/AddressTypeModel'; import { createFeatureToggle } from '@src/util/createFeatureToggle'; import { Store } from 'vuex'; import { TrackingData } from '@src/view_models/TrackingData'; import { CampaignValues } from '@src/view_models/CampaignValues'; import { AddressValidation } from '@src/view_models/Validation'; -import { nextTick } from 'vue'; -import { Validity } from '@src/view_models/Validity'; import { Salutation } from '@src/view_models/Salutation'; import PersonalDataSectionDonationReceipt from '@src/components/pages/donation_form/singlePageFormSections/PersonalDataSectionDonationReceipt.vue'; import BankFields from '@src/components/shared/BankFields.vue'; @@ -36,9 +31,6 @@ const salutations: Salutation[] = [ }, ]; -jest.mock( 'axios' ); -const mockedAxios = axios as jest.Mocked; - describe( 'PersonalDataSectionDonationReceipt.vue', () => { const getWrapper = ( store: Store = createStore() ): { wrapper: VueWrapper, store: Store } => { const wrapper = mount( PersonalDataSectionDonationReceipt, { @@ -117,208 +109,6 @@ describe( 'PersonalDataSectionDonationReceipt.vue', () => { expect( scrollElement.scrollIntoView ).toHaveBeenCalledWith( { behavior: 'smooth' } ); } ); - it( 'shows and hides the error summary', async () => { - const { wrapper, store } = getWrapper(); - - await setPaymentType( store, 'UEB' ); - - await wrapper.find( '#donation-form' ).trigger( 'submit' ); - await nextTick(); - await nextTick(); - - expect( wrapper.find( '.error-summary' ).exists() ).toBeTruthy(); - - await wrapper.find( '#donationReceipt-0' ).trigger( 'change' ); - await wrapper.find( '#addressType-0' ).trigger( 'change' ); - await wrapper.find( '#salutation-0' ).trigger( 'change' ); - - await wrapper.find( '#first-name' ).setValue( 'first-name' ); - await wrapper.find( '#first-name' ).trigger( 'blur' ); - - await wrapper.find( '#last-name' ).setValue( 'last-name' ); - await wrapper.find( '#last-name' ).trigger( 'blur' ); - - await wrapper.find( '#street' ).setValue( 'street' ); - await wrapper.find( '#street' ).trigger( 'blur' ); - - await wrapper.find( '#post-code' ).setValue( 'post-code' ); - await wrapper.find( '#post-code' ).trigger( 'blur' ); - - await wrapper.find( '#city' ).setValue( 'city' ); - await wrapper.find( '#city' ).trigger( 'blur' ); - - await wrapper.find( '#country' ).setValue( 'country' ); - await wrapper.find( '#country' ).trigger( 'blur' ); - - await wrapper.find( '#email' ).setValue( 'joe@dolan.com' ); - await wrapper.find( '#email' ).trigger( 'blur' ); - - expect( wrapper.find( '.error-summary' ).exists() ).toBeFalsy(); - } ); - - it( 'shows and hides the error summary when payment data is invalid', async () => { - jest.useFakeTimers(); - - const { wrapper, store } = getWrapper(); - - await setPaymentType( store, 'BEZ' ); - - await wrapper.find( '#donation-form' ).trigger( 'submit' ); - await nextTick(); - await nextTick(); - - expect( wrapper.find( '.error-summary' ).exists() ).toBeTruthy(); - - await wrapper.find( '#donationReceipt-0' ).trigger( 'change' ); - await wrapper.find( '#addressType-0' ).trigger( 'change' ); - await wrapper.find( '#salutation-0' ).trigger( 'change' ); - - await wrapper.find( '#first-name' ).setValue( 'first-name' ); - await wrapper.find( '#first-name' ).trigger( 'blur' ); - - await wrapper.find( '#last-name' ).setValue( 'last-name' ); - await wrapper.find( '#last-name' ).trigger( 'blur' ); - - await wrapper.find( '#street' ).setValue( 'street' ); - await wrapper.find( '#street' ).trigger( 'blur' ); - - await wrapper.find( '#post-code' ).setValue( 'post-code' ); - await wrapper.find( '#post-code' ).trigger( 'blur' ); - - await wrapper.find( '#city' ).setValue( 'city' ); - await wrapper.find( '#city' ).trigger( 'blur' ); - - await jest.runAllTimersAsync(); - - await wrapper.find( '#country' ).setValue( 'country' ); - await wrapper.find( '#country' ).trigger( 'blur' ); - - await wrapper.find( '#email' ).setValue( 'joe@dolan.com' ); - await wrapper.find( '#email' ).trigger( 'blur' ); - - expect( wrapper.find( '.error-summary' ).exists() ).toBeTruthy(); - - await wrapper.find( '#account-number' ).setValue( 'DE12500105170648489890' ); - await wrapper.find( '#account-number' ).trigger( 'blur' ); - - await flushPromises(); - - expect( wrapper.find( '.error-summary' ).exists() ).toBeFalsy(); - - jest.clearAllMocks(); - } ); - - it( 'handles all error summary clicks when no donation receipt has been selected', async () => { - const { wrapper, store } = getWrapper(); - - await setPaymentType( store, 'BEZ' ); - - await wrapper.find( '#donation-form' ).trigger( 'submit' ); - await nextTick(); - await nextTick(); - - const errorLinks = wrapper.findAll( '.error-summary-list a' ); - - expect( errorLinks.length ).toStrictEqual( 6 ); - - errorLinks.forEach( x => { - expect( wrapper.find( x.attributes( 'href' ) ).exists() ).toBeTruthy(); - expect( wrapper.find( '#' + x.attributes( 'data-scroll-element' ) ).exists() ).toBeTruthy(); - } ); - } ); - - it( 'handles all error summary clicks when donation receipt has been selected', async () => { - jest.useFakeTimers(); - - const { wrapper, store } = getWrapper(); - - await setPaymentType( store, 'BEZ' ); - - await wrapper.find( '#donationReceipt-0' ).trigger( 'change' ); - - await wrapper.find( '#country' ).setValue( 'I am clearly not a country' ); - await wrapper.find( '#country' ).trigger( 'blur' ); - - await jest.runAllTimersAsync(); - - await wrapper.find( '#donation-form' ).trigger( 'submit' ); - await nextTick(); - await nextTick(); - - const errorLinks = wrapper.findAll( '.error-summary-list a' ); - - expect( errorLinks.length ).toStrictEqual( 9 ); - - errorLinks.forEach( x => { - expect( wrapper.find( x.attributes( 'href' ) ).exists() ).toBeTruthy(); - expect( wrapper.find( '#' + x.attributes( 'data-scroll-element' ) ).exists() ).toBeTruthy(); - } ); - - jest.clearAllMocks(); - } ); - - it( 'handles all error summary clicks when address type is person', async () => { - jest.useFakeTimers(); - - const { wrapper, store } = getWrapper(); - - await setPaymentType( store, 'BEZ' ); - - await wrapper.find( '#donationReceipt-0' ).trigger( 'change' ); - await wrapper.find( '#addressType-0' ).trigger( 'change' ); - - await wrapper.find( '#country' ).setValue( 'I am clearly not a country' ); - await wrapper.find( '#country' ).trigger( 'blur' ); - - await jest.runAllTimersAsync(); - - await wrapper.find( '#donation-form' ).trigger( 'submit' ); - await nextTick(); - await nextTick(); - - const errorLinks = wrapper.findAll( '.error-summary-list a' ); - - expect( errorLinks.length ).toStrictEqual( 8 ); - - errorLinks.forEach( x => { - expect( wrapper.find( x.attributes( 'href' ) ).exists() ).toBeTruthy(); - expect( wrapper.find( '#' + x.attributes( 'data-scroll-element' ) ).exists() ).toBeTruthy(); - } ); - - jest.clearAllMocks(); - } ); - - it( 'handles all error summary clicks when address type is company', async () => { - jest.useFakeTimers(); - - const { wrapper, store } = getWrapper(); - - await setPaymentType( store, 'BEZ' ); - - await wrapper.find( '#donationReceipt-0' ).trigger( 'change' ); - - await wrapper.find( '#country' ).setValue( 'I am clearly not a country' ); - await wrapper.find( '#country' ).trigger( 'blur' ); - - await jest.runAllTimersAsync(); - - await wrapper.find( '#addressType-0' ).trigger( 'change' ); - await wrapper.find( '#donation-form' ).trigger( 'submit' ); - await nextTick(); - await nextTick(); - - const errorLinks = wrapper.findAll( '.error-summary-list a' ); - - expect( errorLinks.length ).toStrictEqual( 8 ); - - errorLinks.forEach( x => { - expect( wrapper.find( x.attributes( 'href' ) ).exists() ).toBeTruthy(); - expect( wrapper.find( '#' + x.attributes( 'data-scroll-element' ) ).exists() ).toBeTruthy(); - } ); - - jest.clearAllMocks(); - } ); - it( 'validates the payment section input on page submit', async () => { const { wrapper, store } = getWrapper(); store.dispatch = jest.fn().mockResolvedValue( true ); @@ -327,38 +117,4 @@ describe( 'PersonalDataSectionDonationReceipt.vue', () => { expect( store.dispatch ).toHaveBeenCalledWith( action( 'payment', 'markEmptyValuesAsInvalid' ) ); } ); - - it( 'submits the form', async () => { - const store = createStore(); - await setPaymentType( store, 'UEB' ); - await store.dispatch( action( 'address', 'initializeAddress' ), { - addressType: AddressTypeModel.PERSON, - newsletter: true, - receipt: true, - fields: [ - { name: 'salutation', value: 'Mr', validity: Validity.RESTORED }, - { name: 'title', value: 'Dr', validity: Validity.RESTORED }, - { name: 'firstName', value: 'value', validity: Validity.RESTORED }, - { name: 'lastName', value: 'value', validity: Validity.RESTORED }, - { name: 'street', value: 'value', validity: Validity.RESTORED }, - { name: 'postcode', value: '12345', validity: Validity.RESTORED }, - { name: 'city', value: 'value', validity: Validity.RESTORED }, - { name: 'country', value: 'value', validity: Validity.RESTORED }, - { name: 'email', value: 'value@gmail.com', validity: Validity.RESTORED }, - { name: 'companyName', value: 'value', validity: Validity.RESTORED }, - ], - } ); - - mockedAxios.post.mockResolvedValue( { data: { status: 'OK' } } ); - const { wrapper } = getWrapper( store ); - - const submitForm = wrapper.find( '#donation-form-submit-values' ); - submitForm.element.submit = jest.fn(); - - await wrapper.find( '#donation-form' ).trigger( 'submit' ); - await flushPromises(); - - expect( submitForm.element.submit ).toHaveBeenCalled(); - } ); - } ); diff --git a/tests/unit/components/pages/donation_form/single_page_form/PersonalDataSectionDonationReceiptStreetAutoComplete.spec.ts b/tests/unit/components/pages/donation_form/single_page_form/PersonalDataSectionDonationReceiptStreetAutoComplete.spec.ts index 1506f1c9d..ba8f28bd5 100644 --- a/tests/unit/components/pages/donation_form/single_page_form/PersonalDataSectionDonationReceiptStreetAutoComplete.spec.ts +++ b/tests/unit/components/pages/donation_form/single_page_form/PersonalDataSectionDonationReceiptStreetAutoComplete.spec.ts @@ -1,16 +1,11 @@ -import { flushPromises, mount, VueWrapper } from '@vue/test-utils'; - -import axios from 'axios'; +import { mount, VueWrapper } from '@vue/test-utils'; import { createStore } from '@src/store/donation_store'; import { action } from '@src/store/util'; -import { AddressTypeModel } from '@src/view_models/AddressTypeModel'; import { createFeatureToggle } from '@src/util/createFeatureToggle'; import { Store } from 'vuex'; import { TrackingData } from '@src/view_models/TrackingData'; import { CampaignValues } from '@src/view_models/CampaignValues'; import { AddressValidation } from '@src/view_models/Validation'; -import { nextTick } from 'vue'; -import { Validity } from '@src/view_models/Validity'; import { Salutation } from '@src/view_models/Salutation'; import PersonalDataSectionDonationReceipt from '@src/components/pages/donation_form/singlePageFormSections/PersonalDataSectionDonationReceipt.vue'; import BankFields from '@src/components/shared/BankFields.vue'; @@ -36,9 +31,6 @@ const salutations: Salutation[] = [ }, ]; -jest.mock( 'axios' ); -const mockedAxios = axios as jest.Mocked; - describe( 'PersonalDataSectionDonationReceipt.vue (With Street Autocomplete)', () => { const getWrapper = ( store: Store = createStore() ): { wrapper: VueWrapper, store: Store } => { const wrapper = mount( PersonalDataSectionDonationReceipt, { @@ -120,208 +112,6 @@ describe( 'PersonalDataSectionDonationReceipt.vue (With Street Autocomplete)', ( expect( scrollElement.scrollIntoView ).toHaveBeenCalledWith( { behavior: 'smooth' } ); } ); - it( 'shows and hides the error summary', async () => { - const { wrapper, store } = getWrapper(); - - await setPaymentTypeAndInitializeOtherPaymentValues( store, 'UEB' ); - - await wrapper.find( '#donation-form' ).trigger( 'submit' ); - await nextTick(); - await nextTick(); - - expect( wrapper.find( '.error-summary' ).exists() ).toBeTruthy(); - - await wrapper.find( '#donationReceipt-0' ).trigger( 'change' ); - await wrapper.find( '#addressType-0' ).trigger( 'change' ); - await wrapper.find( '#salutation-0' ).trigger( 'change' ); - - await wrapper.find( '#first-name' ).setValue( 'first-name' ); - await wrapper.find( '#first-name' ).trigger( 'blur' ); - - await wrapper.find( '#last-name' ).setValue( 'last-name' ); - await wrapper.find( '#last-name' ).trigger( 'blur' ); - - await wrapper.find( '#street' ).setValue( 'street' ); - await wrapper.find( '#street' ).trigger( 'blur' ); - - await wrapper.find( '#post-code' ).setValue( 'post-code' ); - await wrapper.find( '#post-code' ).trigger( 'blur' ); - - await wrapper.find( '#city' ).setValue( 'city' ); - await wrapper.find( '#city' ).trigger( 'blur' ); - - await wrapper.find( '#country' ).setValue( 'country' ); - await wrapper.find( '#country' ).trigger( 'blur' ); - - await wrapper.find( '#email' ).setValue( 'joe@dolan.com' ); - await wrapper.find( '#email' ).trigger( 'blur' ); - - expect( wrapper.find( '.error-summary' ).exists() ).toBeFalsy(); - } ); - - it( 'shows and hides the error summary when payment data is invalid', async () => { - jest.useFakeTimers(); - - const { wrapper, store } = getWrapper(); - - await setPaymentTypeAndInitializeOtherPaymentValues( store, 'BEZ' ); - - await wrapper.find( '#donation-form' ).trigger( 'submit' ); - await nextTick(); - await nextTick(); - - expect( wrapper.find( '.error-summary' ).exists() ).toBeTruthy(); - - await wrapper.find( '#donationReceipt-0' ).trigger( 'change' ); - await wrapper.find( '#addressType-0' ).trigger( 'change' ); - await wrapper.find( '#salutation-0' ).trigger( 'change' ); - - await wrapper.find( '#first-name' ).setValue( 'first-name' ); - await wrapper.find( '#first-name' ).trigger( 'blur' ); - - await wrapper.find( '#last-name' ).setValue( 'last-name' ); - await wrapper.find( '#last-name' ).trigger( 'blur' ); - - await wrapper.find( '#street' ).setValue( 'street' ); - await wrapper.find( '#street' ).trigger( 'blur' ); - - await wrapper.find( '#post-code' ).setValue( 'post-code' ); - await wrapper.find( '#post-code' ).trigger( 'blur' ); - - await wrapper.find( '#city' ).setValue( 'city' ); - await wrapper.find( '#city' ).trigger( 'blur' ); - - await jest.runAllTimersAsync(); - - await wrapper.find( '#country' ).setValue( 'country' ); - await wrapper.find( '#country' ).trigger( 'blur' ); - - await wrapper.find( '#email' ).setValue( 'joe@dolan.com' ); - await wrapper.find( '#email' ).trigger( 'blur' ); - - expect( wrapper.find( '.error-summary' ).exists() ).toBeTruthy(); - - await wrapper.find( '#account-number' ).setValue( 'DE12500105170648489890' ); - await wrapper.find( '#account-number' ).trigger( 'blur' ); - - await flushPromises(); - - expect( wrapper.find( '.error-summary' ).exists() ).toBeFalsy(); - - jest.clearAllMocks(); - } ); - - it( 'handles all error summary clicks when no donation receipt has been selected', async () => { - const { wrapper, store } = getWrapper(); - - await setPaymentTypeAndInitializeOtherPaymentValues( store, 'BEZ' ); - - await wrapper.find( '#donation-form' ).trigger( 'submit' ); - await nextTick(); - await nextTick(); - - const errorLinks = wrapper.findAll( '.error-summary-list a' ); - - expect( errorLinks.length ).toStrictEqual( 6 ); - - errorLinks.forEach( x => { - expect( wrapper.find( x.attributes( 'href' ) ).exists() ).toBeTruthy(); - expect( wrapper.find( '#' + x.attributes( 'data-scroll-element' ) ).exists() ).toBeTruthy(); - } ); - } ); - - it( 'handles all error summary clicks when donation receipt has been selected', async () => { - jest.useFakeTimers(); - - const { wrapper, store } = getWrapper(); - - await setPaymentTypeAndInitializeOtherPaymentValues( store, 'BEZ' ); - - await wrapper.find( '#donationReceipt-0' ).trigger( 'change' ); - - await wrapper.find( '#country' ).setValue( 'I am clearly not a country' ); - await wrapper.find( '#country' ).trigger( 'blur' ); - - await jest.runAllTimersAsync(); - - await wrapper.find( '#donation-form' ).trigger( 'submit' ); - await nextTick(); - await nextTick(); - - const errorLinks = wrapper.findAll( '.error-summary-list a' ); - - expect( errorLinks.length ).toStrictEqual( 9 ); - - errorLinks.forEach( x => { - expect( wrapper.find( x.attributes( 'href' ) ).exists() ).toBeTruthy(); - expect( wrapper.find( '#' + x.attributes( 'data-scroll-element' ) ).exists() ).toBeTruthy(); - } ); - - jest.clearAllMocks(); - } ); - - it( 'handles all error summary clicks when address type is person', async () => { - jest.useFakeTimers(); - - const { wrapper, store } = getWrapper(); - - await setPaymentTypeAndInitializeOtherPaymentValues( store, 'BEZ' ); - - await wrapper.find( '#donationReceipt-0' ).trigger( 'change' ); - await wrapper.find( '#addressType-0' ).trigger( 'change' ); - - await wrapper.find( '#country' ).setValue( 'I am clearly not a country' ); - await wrapper.find( '#country' ).trigger( 'blur' ); - - await jest.runAllTimersAsync(); - - await wrapper.find( '#donation-form' ).trigger( 'submit' ); - await nextTick(); - await nextTick(); - - const errorLinks = wrapper.findAll( '.error-summary-list a' ); - - expect( errorLinks.length ).toStrictEqual( 8 ); - - errorLinks.forEach( x => { - expect( wrapper.find( x.attributes( 'href' ) ).exists() ).toBeTruthy(); - expect( wrapper.find( '#' + x.attributes( 'data-scroll-element' ) ).exists() ).toBeTruthy(); - } ); - - jest.clearAllMocks(); - } ); - - it( 'handles all error summary clicks when address type is company', async () => { - jest.useFakeTimers(); - - const { wrapper, store } = getWrapper(); - - await setPaymentTypeAndInitializeOtherPaymentValues( store, 'BEZ' ); - - await wrapper.find( '#donationReceipt-0' ).trigger( 'change' ); - - await wrapper.find( '#country' ).setValue( 'I am clearly not a country' ); - await wrapper.find( '#country' ).trigger( 'blur' ); - - await jest.runAllTimersAsync(); - - await wrapper.find( '#addressType-0' ).trigger( 'change' ); - await wrapper.find( '#donation-form' ).trigger( 'submit' ); - await nextTick(); - await nextTick(); - - const errorLinks = wrapper.findAll( '.error-summary-list a' ); - - expect( errorLinks.length ).toStrictEqual( 8 ); - - errorLinks.forEach( x => { - expect( wrapper.find( x.attributes( 'href' ) ).exists() ).toBeTruthy(); - expect( wrapper.find( '#' + x.attributes( 'data-scroll-element' ) ).exists() ).toBeTruthy(); - } ); - - jest.clearAllMocks(); - } ); - it( 'validates the payment section input on page submit', async () => { const { wrapper, store } = getWrapper(); store.dispatch = jest.fn().mockResolvedValue( true ); @@ -330,38 +120,4 @@ describe( 'PersonalDataSectionDonationReceipt.vue (With Street Autocomplete)', ( expect( store.dispatch ).toHaveBeenCalledWith( action( 'payment', 'markEmptyValuesAsInvalid' ) ); } ); - - it( 'submits the form', async () => { - const store = createStore(); - await setPaymentTypeAndInitializeOtherPaymentValues( store, 'UEB' ); - await store.dispatch( action( 'address', 'initializeAddress' ), { - addressType: AddressTypeModel.PERSON, - newsletter: true, - receipt: true, - fields: [ - { name: 'salutation', value: 'Mr', validity: Validity.RESTORED }, - { name: 'title', value: 'Dr', validity: Validity.RESTORED }, - { name: 'firstName', value: 'value', validity: Validity.RESTORED }, - { name: 'lastName', value: 'value', validity: Validity.RESTORED }, - { name: 'street', value: 'value', validity: Validity.RESTORED }, - { name: 'postcode', value: '12345', validity: Validity.RESTORED }, - { name: 'city', value: 'value', validity: Validity.RESTORED }, - { name: 'country', value: 'value', validity: Validity.RESTORED }, - { name: 'email', value: 'value@gmail.com', validity: Validity.RESTORED }, - { name: 'companyName', value: 'value', validity: Validity.RESTORED }, - ], - } ); - - mockedAxios.post.mockResolvedValue( { data: { status: 'OK' } } ); - const { wrapper } = getWrapper( store ); - - const submitForm = wrapper.find( '#donation-form-submit-values' ); - submitForm.element.submit = jest.fn(); - - await wrapper.find( '#donation-form' ).trigger( 'submit' ); - await flushPromises(); - - expect( submitForm.element.submit ).toHaveBeenCalled(); - } ); - } ); diff --git a/tests/unit/components/pages/donation_form/single_page_form/PersonalDataSectionStreetAutoComplete.spec.ts b/tests/unit/components/pages/donation_form/single_page_form/PersonalDataSectionStreetAutoComplete.spec.ts index b7bc98804..0cd1c298b 100644 --- a/tests/unit/components/pages/donation_form/single_page_form/PersonalDataSectionStreetAutoComplete.spec.ts +++ b/tests/unit/components/pages/donation_form/single_page_form/PersonalDataSectionStreetAutoComplete.spec.ts @@ -1,6 +1,5 @@ -import { flushPromises, mount, VueWrapper } from '@vue/test-utils'; +import { mount, VueWrapper } from '@vue/test-utils'; -import axios from 'axios'; import PersonalDataSection from '@src/components/pages/donation_form/singlePageFormSections/PersonalDataSection.vue'; import { createStore } from '@src/store/donation_store'; import { action } from '@src/store/util'; @@ -12,7 +11,6 @@ import { CampaignValues } from '@src/view_models/CampaignValues'; import { AddressValidation } from '@src/view_models/Validation'; import { nextTick } from 'vue'; import AddressTypeBasic from '@src/components/pages/donation_form/AddressTypeBasic.vue'; -import { Validity } from '@src/view_models/Validity'; import { Salutation } from '@src/view_models/Salutation'; import { FakeBankValidationResource } from '@test/unit/TestDoubles/FakeBankValidationResource'; import BankFields from '@src/components/shared/BankFields.vue'; @@ -37,9 +35,6 @@ const salutations: Salutation[] = [ }, ]; -jest.mock( 'axios' ); -const mockedAxios = axios as jest.Mocked; - describe( 'PersonalDataSection.vue (With Street Autocomplete)', () => { const getWrapper = ( store: Store = createStore() ): { wrapper: VueWrapper, store: Store } => { const wrapper = mount( PersonalDataSection, { @@ -133,137 +128,6 @@ describe( 'PersonalDataSection.vue (With Street Autocomplete)', () => { expect( scrollElement.scrollIntoView ).toHaveBeenCalledWith( { behavior: 'smooth' } ); } ); - it( 'shows and hides the error summary', async () => { - jest.useFakeTimers(); - - const { wrapper, store } = getWrapper(); - - await setPaymentTypeAndInitializeOtherPaymentValues( store, 'UEB' ); - - await wrapper.find( '#submit-btn' ).trigger( 'click' ); - await nextTick(); - await nextTick(); - - expect( wrapper.find( '.error-summary' ).exists() ).toBeTruthy(); - - await wrapper.find( '#addressType-0' ).trigger( 'change' ); - await wrapper.find( '#person-salutation-0' ).trigger( 'change' ); - - await wrapper.find( '#person-first-name' ).setValue( 'first-name' ); - await wrapper.find( '#person-first-name' ).trigger( 'blur' ); - - await wrapper.find( '#person-last-name' ).setValue( 'last-name' ); - await wrapper.find( '#person-last-name' ).trigger( 'blur' ); - - await wrapper.find( '#person-street' ).setValue( 'street' ); - await wrapper.find( '#person-street' ).trigger( 'blur' ); - - await wrapper.find( '#person-post-code' ).setValue( 'post-code' ); - await wrapper.find( '#person-post-code' ).trigger( 'blur' ); - - await wrapper.find( '#person-city' ).setValue( 'city' ); - await wrapper.find( '#person-city' ).trigger( 'blur' ); - - await wrapper.find( '#person-country' ).setValue( 'country' ); - await wrapper.find( '#person-country' ).trigger( 'blur' ); - - await wrapper.find( '#person-email' ).setValue( 'joe@dolan.com' ); - await wrapper.find( '#person-email' ).trigger( 'blur' ); - - await jest.runAllTimersAsync(); - - expect( wrapper.find( '.error-summary' ).exists() ).toBeFalsy(); - - jest.clearAllMocks(); - } ); - - it( 'shows and hides the error summary when payment data is invalid', async () => { - jest.useFakeTimers(); - - const { wrapper, store } = getWrapper(); - - await setPaymentTypeAndInitializeOtherPaymentValues( store, 'BEZ' ); - - await wrapper.find( '#submit-btn' ).trigger( 'click' ); - await nextTick(); - await nextTick(); - - expect( wrapper.find( '.error-summary' ).exists() ).toBeTruthy(); - - await wrapper.find( '#addressType-0' ).trigger( 'change' ); - await wrapper.find( '#person-salutation-0' ).trigger( 'change' ); - - await wrapper.find( '#person-first-name' ).setValue( 'first-name' ); - await wrapper.find( '#person-first-name' ).trigger( 'blur' ); - - await wrapper.find( '#person-last-name' ).setValue( 'last-name' ); - await wrapper.find( '#person-last-name' ).trigger( 'blur' ); - - await wrapper.find( '#person-street' ).setValue( 'street' ); - await wrapper.find( '#person-street' ).trigger( 'blur' ); - - await wrapper.find( '#person-post-code' ).setValue( 'post-code' ); - await wrapper.find( '#person-post-code' ).trigger( 'blur' ); - - await wrapper.find( '#person-city' ).setValue( 'city' ); - await wrapper.find( '#person-city' ).trigger( 'blur' ); - - await jest.runAllTimersAsync(); - - await wrapper.find( '#person-country' ).setValue( 'country' ); - await wrapper.find( '#person-country' ).trigger( 'blur' ); - - await wrapper.find( '#person-email' ).setValue( 'joe@dolan.com' ); - await wrapper.find( '#person-email' ).trigger( 'blur' ); - - expect( wrapper.find( '.error-summary' ).exists() ).toBeTruthy(); - - await wrapper.find( '#account-number' ).setValue( 'DE12500105170648489890' ); - await wrapper.find( '#account-number' ).trigger( 'blur' ); - - await flushPromises(); - - expect( wrapper.find( '.error-summary' ).exists() ).toBeFalsy(); - - jest.clearAllMocks(); - } ); - - test.each( [ - [ '', 10 ], - [ '#addressType-0', 9 ], - [ '#addressType-1', 7 ], - ] )( 'focuses inputs on error summary clicks', async ( addressTypeSelector: string, numberOfErrors: number ) => { - jest.useFakeTimers(); - - const { wrapper, store } = getWrapper(); - - await setPaymentTypeAndInitializeOtherPaymentValues( store, 'BEZ' ); - - if ( addressTypeSelector !== '' ) { - await wrapper.find( addressTypeSelector ).trigger( 'change' ); - } - - await wrapper.find( '#person-country' ).setValue( 'I am clearly not a country' ); - await wrapper.find( '#person-country' ).trigger( 'blur' ); - - await jest.runAllTimersAsync(); - - await wrapper.find( '#submit-btn' ).trigger( 'click' ); - await nextTick(); - await nextTick(); - - const errorLinks = wrapper.findAll( '.error-summary-list a' ); - - expect( errorLinks.length ).toStrictEqual( numberOfErrors ); - - errorLinks.forEach( x => { - expect( wrapper.find( x.attributes( 'href' ) ).exists() ).toBeTruthy(); - expect( wrapper.find( '#' + x.attributes( 'data-scroll-element' ) ).exists() ).toBeTruthy(); - } ); - - jest.clearAllMocks(); - } ); - it( 'updates full selected', async () => { const { wrapper } = getWrapper(); @@ -282,38 +146,4 @@ describe( 'PersonalDataSection.vue (With Street Autocomplete)', () => { expect( store.dispatch ).toHaveBeenCalledWith( action( 'payment', 'markEmptyValuesAsInvalid' ) ); } ); - - it( 'submits the form', async () => { - const store = createStore(); - await setPaymentTypeAndInitializeOtherPaymentValues( store, 'UEB' ); - await store.dispatch( action( 'address', 'initializeAddress' ), { - addressType: AddressTypeModel.ANON, - newsletter: true, - receipt: true, - fields: [ - { name: 'salutation', value: 'Mr', validity: Validity.RESTORED }, - { name: 'title', value: 'Dr', validity: Validity.RESTORED }, - { name: 'firstName', value: 'value', validity: Validity.RESTORED }, - { name: 'lastName', value: 'value', validity: Validity.RESTORED }, - { name: 'street', value: 'value', validity: Validity.RESTORED }, - { name: 'postcode', value: '12345', validity: Validity.RESTORED }, - { name: 'city', value: 'value', validity: Validity.RESTORED }, - { name: 'country', value: 'value', validity: Validity.RESTORED }, - { name: 'email', value: 'value@gmail.com', validity: Validity.RESTORED }, - { name: 'companyName', value: 'value', validity: Validity.RESTORED }, - ], - } ); - - mockedAxios.post.mockResolvedValue( { data: { status: 'OK' } } ); - const { wrapper } = getWrapper( store ); - - const submitForm = wrapper.find( '#submit-form' ); - submitForm.element.submit = jest.fn(); - - await wrapper.find( '#submit-btn' ).trigger( 'click' ); - await flushPromises(); - - expect( submitForm.element.submit ).toHaveBeenCalled(); - } ); - } );