From 91a1923fd0b05380733af2359091f4c7a4c89672 Mon Sep 17 00:00:00 2001 From: Abban Dunne Date: Thu, 7 Nov 2024 12:33:41 +0100 Subject: [PATCH] Prepare CTRL for C24_WMDE_Desktop_DE_11 Based on CTRL of test 10 Banners are hidden under 800px Ticket: https://phabricator.wikimedia.org/T379246 --- .../C24_WMDE_Desktop_DE_11/banner_var.ts | 4 +- .../components/BannerCtrl.vue | 2 + .../components/BannerVar.vue | 163 ---------------- .../C24_WMDE_Desktop_DE_11/form_items_var.ts | 21 --- .../styles/MinimisedBanner.scss | 111 ----------- .../C24_WMDE_Desktop_DE_11/styles/styles.scss | 4 +- src/components/composables/useBannerHider.ts | 19 ++ src/domain/CloseChoices.ts | 2 + .../components/BannerCtrl.spec.ts | 12 +- .../components/BannerVar.spec.ts | 177 ------------------ .../components/FallbackBanner.spec.ts | 2 +- test/features/MainBanner.ts | 17 ++ 12 files changed, 53 insertions(+), 481 deletions(-) delete mode 100644 banners/desktop/C24_WMDE_Desktop_DE_11/components/BannerVar.vue delete mode 100644 banners/desktop/C24_WMDE_Desktop_DE_11/form_items_var.ts delete mode 100644 banners/desktop/C24_WMDE_Desktop_DE_11/styles/MinimisedBanner.scss create mode 100644 src/components/composables/useBannerHider.ts delete mode 100644 test/banners/desktop/C24_WMDE_Desktop_DE_11/components/BannerVar.spec.ts diff --git a/banners/desktop/C24_WMDE_Desktop_DE_11/banner_var.ts b/banners/desktop/C24_WMDE_Desktop_DE_11/banner_var.ts index 2ebfc85e4..51ffcb4de 100644 --- a/banners/desktop/C24_WMDE_Desktop_DE_11/banner_var.ts +++ b/banners/desktop/C24_WMDE_Desktop_DE_11/banner_var.ts @@ -3,7 +3,7 @@ import { createVueApp } from '@src/createVueApp'; import './styles/styles.scss'; import BannerConductor from '@src/components/BannerConductor/FallbackBannerConductor.vue'; -import Banner from './components/BannerVar.vue'; +import Banner from './components/BannerCtrl.vue'; import FallbackBanner from './components/FallbackBanner.vue'; import { UrlRuntimeEnvironment } from '@src/utils/RuntimeEnvironment'; import { WindowResizeHandler } from '@src/utils/ResizeHandler'; @@ -25,7 +25,7 @@ import messages from './messages'; import { LocaleFactoryDe } from '@src/utils/LocaleFactory/LocaleFactoryDe'; // Channel specific form setup -import { createFormItems } from './form_items_var'; +import { createFormItems } from './form_items'; import { createFormActions } from '@src/createFormActions'; const date = new Date(); diff --git a/banners/desktop/C24_WMDE_Desktop_DE_11/components/BannerCtrl.vue b/banners/desktop/C24_WMDE_Desktop_DE_11/components/BannerCtrl.vue index 3db33caba..54ea355f0 100644 --- a/banners/desktop/C24_WMDE_Desktop_DE_11/components/BannerCtrl.vue +++ b/banners/desktop/C24_WMDE_Desktop_DE_11/components/BannerCtrl.vue @@ -105,6 +105,7 @@ import SoftClose from '@src/components/SoftClose/SoftClose.vue'; import { LocalCloseTracker } from '@src/utils/LocalCloseTracker'; import { BannerSubmitOnReturnEvent } from '@src/tracking/events/BannerSubmitOnReturnEvent'; import { Tracker } from '@src/tracking/Tracker'; +import { useBannerHider } from '@src/components/composables/useBannerHider'; enum ContentStates { Main = 'wmde-banner-wrapper--main', @@ -125,6 +126,7 @@ interface Props { const props = defineProps(); const emit = defineEmits( [ 'bannerClosed', 'bannerContentChanged' ] ); +useBannerHider( 800, emit ); const tracker = inject( 'tracker' ); diff --git a/banners/desktop/C24_WMDE_Desktop_DE_11/components/BannerVar.vue b/banners/desktop/C24_WMDE_Desktop_DE_11/components/BannerVar.vue deleted file mode 100644 index 3db33caba..000000000 --- a/banners/desktop/C24_WMDE_Desktop_DE_11/components/BannerVar.vue +++ /dev/null @@ -1,163 +0,0 @@ - - - diff --git a/banners/desktop/C24_WMDE_Desktop_DE_11/form_items_var.ts b/banners/desktop/C24_WMDE_Desktop_DE_11/form_items_var.ts deleted file mode 100644 index cdd99a20b..000000000 --- a/banners/desktop/C24_WMDE_Desktop_DE_11/form_items_var.ts +++ /dev/null @@ -1,21 +0,0 @@ -import FormItemsBuilder from '@src/utils/FormItemsBuilder/FormItemsBuilder'; -import { Translator } from '@src/Translator'; -import { DonationFormItems } from '@src/utils/FormItemsBuilder/DonationFormItems'; -import { Intervals } from '@src/utils/FormItemsBuilder/fields/Intervals'; -import { PaymentMethods } from '@src/utils/FormItemsBuilder/fields/PaymentMethods'; -import { NumberFormatter } from '@src/utils/DynamicContent/formatters/NumberFormatter'; - -export function createFormItems( translations: Translator, amountFormatter: NumberFormatter ): DonationFormItems { - return new FormItemsBuilder( translations, amountFormatter ) - .setIntervals( - Intervals.ONCE, - Intervals.MONTHLY - ) - .setAmounts( 5, 10, 20, 25, 50, 100 ) - .setPaymentMethods( - PaymentMethods.PAYPAL, - PaymentMethods.BANK_TRANSFER, - PaymentMethods.CREDIT_CARD, - PaymentMethods.DIRECT_DEBIT - ).getItems(); -} diff --git a/banners/desktop/C24_WMDE_Desktop_DE_11/styles/MinimisedBanner.scss b/banners/desktop/C24_WMDE_Desktop_DE_11/styles/MinimisedBanner.scss deleted file mode 100644 index fd1480727..000000000 --- a/banners/desktop/C24_WMDE_Desktop_DE_11/styles/MinimisedBanner.scss +++ /dev/null @@ -1,111 +0,0 @@ -@use 'src/themes/Svingle/variables/globals'; - -.wmde-banner { - &-minimised { - padding: 12px 24px 0; - - &-content { - display: flex; - - &-message { - flex: 1 1 auto; - display: flex; - flex-direction: column; - justify-content: center; - padding: 11px 15px 11px 34px; - color: var( --color-white ); - background-color: var( --color-secondary ); - border: none; - border-radius: 9px; - font-size: 14px; - - svg { - float: left; - margin: 10px 0 0 -22px; - } - } - - &-button { - flex: 0 0 auto; - display: flex; - flex-direction: column; - justify-content: end; - padding-left: 30px; - } - } - - &-title { - font-size: 18px; - font-weight: bold; - } - - &-submit-button { - width: 300px; - background: var( --color-primary ); - color: var( --color-white ); - font-weight: bold; - line-height: 36px; - border: 0; - border-radius: 18px; - padding: 0 10px; - transition: background-color 500ms globals.$banner-easing; - cursor: pointer; - - &:hover, - &:focus { - background: var( --color-primary-hover ); - } - } - - &-button-group { - position: absolute; - z-index: 2; - top: 12px; - right: 12px; - height: 26px; - border: 2px solid var( --color-secondary ); - border-radius: 13px; - padding: 0 10px; - display: flex; - align-items: center; - - .wmde-banner-close { - height: 16px; - width: 16px; - position: static; - - svg path { - fill: var( --color-secondary ); - } - } - } - - &-minimise, - &-maximise { - background: none; - border: none; - cursor: pointer; - color: var( --color-secondary ); - padding-right: 8px; - margin-right: 8px; - border-right: 1px solid #bfbfbf; - font-size: 14px; - font-weight: bold; - - svg { - width: 20px; - - path { - fill: var( --color-secondary ); - } - } - } - - &-minimise { - svg { - transform: rotate( 180deg ); - margin-left: 3px; - } - } - } -} diff --git a/banners/desktop/C24_WMDE_Desktop_DE_11/styles/styles.scss b/banners/desktop/C24_WMDE_Desktop_DE_11/styles/styles.scss index ec3e1c14d..ff644c870 100644 --- a/banners/desktop/C24_WMDE_Desktop_DE_11/styles/styles.scss +++ b/banners/desktop/C24_WMDE_Desktop_DE_11/styles/styles.scss @@ -37,9 +37,7 @@ @use 'src/themes/Svingle/Footer/SelectionInput'; @use 'src/themes/Svingle/Message/Message'; @use 'src/themes/Svingle/SoftClose/SoftClose'; -@use 'src/themes/Svingle/Slider/KeenSlider' with ( - $margin-bottom: 5px -); +@use 'src/themes/Svingle/Slider/KeenSlider'; /** * Fallback banner with "Fijitiv" theme diff --git a/src/components/composables/useBannerHider.ts b/src/components/composables/useBannerHider.ts new file mode 100644 index 000000000..5624c4430 --- /dev/null +++ b/src/components/composables/useBannerHider.ts @@ -0,0 +1,19 @@ +import { EmitFn, onMounted, onUnmounted } from 'vue'; +import { CloseEvent } from '@src/tracking/events/CloseEvent'; +import { CloseChoices } from '@src/domain/CloseChoices'; + +export function useBannerHider( hideUnder: number, emit: EmitFn<'bannerClosed'[]> ): void { + const onResize = (): void => { + if ( window.innerWidth < hideUnder ) { + emit( 'bannerClosed', new CloseEvent( 'MainBanner', CloseChoices.WindowSizeBelowMin ) ); + } + }; + + onMounted( () => { + window.addEventListener( 'resize', onResize ); + } ); + + onUnmounted( () => { + window.removeEventListener( 'resize', onResize ); + } ); +} diff --git a/src/domain/CloseChoices.ts b/src/domain/CloseChoices.ts index e2ee1a3dc..4863639ba 100644 --- a/src/domain/CloseChoices.ts +++ b/src/domain/CloseChoices.ts @@ -11,4 +11,6 @@ export enum CloseChoices { NoMoreBannersForCampaign = 'no-more-banners', /** user clicked on the already donated link */ AlreadyDonated = 'already-donated', + /** window was resized below the threshold */ + WindowSizeBelowMin = 'window-size-below-min', } diff --git a/test/banners/desktop/C24_WMDE_Desktop_DE_11/components/BannerCtrl.spec.ts b/test/banners/desktop/C24_WMDE_Desktop_DE_11/components/BannerCtrl.spec.ts index 36fc9588d..894f60480 100644 --- a/test/banners/desktop/C24_WMDE_Desktop_DE_11/components/BannerCtrl.spec.ts +++ b/test/banners/desktop/C24_WMDE_Desktop_DE_11/components/BannerCtrl.spec.ts @@ -1,6 +1,6 @@ import { afterEach, beforeEach, describe, test, vi } from 'vitest'; import { mount, VueWrapper } from '@vue/test-utils'; -import Banner from '@banners/desktop/C24_WMDE_Desktop_DE_10/components/BannerCtrl.vue'; +import Banner from '@banners/desktop/C24_WMDE_Desktop_DE_11/components/BannerCtrl.vue'; import { BannerStates } from '@src/components/BannerConductor/StateMachine/BannerStates'; import { newDynamicContent } from '@test/banners/dynamicCampaignContent'; import { useOfFundsContent } from '@test/banners/useOfFundsContent'; @@ -17,7 +17,7 @@ import { donationFormFeatures } from '@test/features/forms/MainDonation_UpgradeT import { useFormModel } from '@src/components/composables/useFormModel'; import { resetFormModel } from '@test/resetFormModel'; import { DynamicContent } from '@src/utils/DynamicContent/DynamicContent'; -import { bannerMainFeatures } from '@test/features/MainBanner'; +import { bannerAutoHideFeatures, bannerMainFeatures } from '@test/features/MainBanner'; import { formActionSwitchFeatures } from '@test/features/form_action_switch/MainDonation_UpgradeToYearlyButton'; import { softCloseFeatures } from '@test/features/SoftCloseDesktop'; import { alreadyDonatedModalFeatures } from '@test/features/AlreadyDonatedModal'; @@ -28,7 +28,7 @@ const formModel = useFormModel(); const translator = ( key: string ): string => key; let tracker: Tracker; -describe( 'BannerVar.vue', () => { +describe( 'BannerCtrl.vue', () => { beforeEach( () => { resetFormModel( formModel ); @@ -81,6 +81,12 @@ describe( 'BannerVar.vue', () => { ] )( '%s', async ( testName: string ) => { await bannerMainFeatures[ testName ]( getWrapper() ); } ); + + test.each( [ + [ 'expectClosesBannerWhenWindowBecomesSmall' ] + ] )( '%s', async ( testName: string ) => { + await bannerAutoHideFeatures[ testName ]( getWrapper ); + } ); } ); describe( 'Content', () => { diff --git a/test/banners/desktop/C24_WMDE_Desktop_DE_11/components/BannerVar.spec.ts b/test/banners/desktop/C24_WMDE_Desktop_DE_11/components/BannerVar.spec.ts deleted file mode 100644 index 6b0f6915a..000000000 --- a/test/banners/desktop/C24_WMDE_Desktop_DE_11/components/BannerVar.spec.ts +++ /dev/null @@ -1,177 +0,0 @@ -import { afterEach, beforeEach, describe, test, vi } from 'vitest'; -import { mount, VueWrapper } from '@vue/test-utils'; -import Banner from '@banners/desktop/C24_WMDE_Desktop_DE_10/components/BannerVar.vue'; -import { BannerStates } from '@src/components/BannerConductor/StateMachine/BannerStates'; -import { newDynamicContent } from '@test/banners/dynamicCampaignContent'; -import { useOfFundsContent } from '@test/banners/useOfFundsContent'; -import { formItems } from '@test/banners/formItems'; -import { CurrencyEn } from '@src/utils/DynamicContent/formatters/CurrencyEn'; -import { useOfFundsFeatures } from '@test/features/UseOfFunds'; -import { - bannerContentAnimatedTextFeatures, - bannerContentDateAndTimeFeatures, - bannerContentDisplaySwitchFeatures, - bannerContentFeatures -} from '@test/features/BannerContent'; -import { donationFormFeatures } from '@test/features/forms/MainDonation_UpgradeToYearlyButton'; -import { useFormModel } from '@src/components/composables/useFormModel'; -import { resetFormModel } from '@test/resetFormModel'; -import { DynamicContent } from '@src/utils/DynamicContent/DynamicContent'; -import { bannerMainFeatures } from '@test/features/MainBanner'; -import { formActionSwitchFeatures } from '@test/features/form_action_switch/MainDonation_UpgradeToYearlyButton'; -import { softCloseFeatures } from '@test/features/SoftCloseDesktop'; -import { alreadyDonatedModalFeatures } from '@test/features/AlreadyDonatedModal'; -import { softCloseSubmitTrackingFeaturesDesktop } from '@test/features/SoftCloseSubmitTrackingDesktop'; -import { Tracker } from '@src/tracking/Tracker'; - -const formModel = useFormModel(); -const translator = ( key: string ): string => key; -let tracker: Tracker; - -describe( 'BannerVar.vue', () => { - - beforeEach( () => { - resetFormModel( formModel ); - vi.useFakeTimers(); - tracker = { - trackEvent: vi.fn() - }; - } ); - - afterEach( () => { - vi.restoreAllMocks(); - vi.useRealTimers(); - } ); - - const getWrapper = ( dynamicContent: DynamicContent = null ): VueWrapper => { - return mount( Banner, { - attachTo: document.body, - props: { - bannerState: BannerStates.Pending, - useOfFundsContent, - remainingImpressions: 10, - localCloseTracker: { - getItem: () => '', - setItem: () => {} - } - }, - global: { - mocks: { - $translate: translator - }, - provide: { - translator: { translate: translator }, - dynamicCampaignText: dynamicContent ?? newDynamicContent(), - currentCampaignTimePercentage: 42, - formActions: { - donateWithAddressAction: 'https://example.com/with-address', - donateAnonymouslyAction: 'https://example.com/without-address' - }, - currencyFormatter: new CurrencyEn(), - formItems, - tracker - } - } - } ); - }; - - describe( 'Main Banner', () => { - test.each( [ - [ 'expectDoesNotEmitCloseEvent' ] - ] )( '%s', async ( testName: string ) => { - await bannerMainFeatures[ testName ]( getWrapper() ); - } ); - } ); - - describe( 'Content', () => { - test.each( [ - [ 'expectSlideShowPlaysWhenBecomesVisible' ], - [ 'expectSlideShowStopsOnFormInteraction' ] - ] )( '%s', async ( testName: string ) => { - await bannerContentFeatures[ testName ]( getWrapper() ); - } ); - - test.each( [ - [ 'expectShowsSlideShowOnSmallSizes' ], - [ 'expectShowsMessageOnLargeSizes' ] - ] )( '%s', async ( testName: string ) => { - await bannerContentDisplaySwitchFeatures[ testName ]( getWrapper, 1300 ); - } ); - - test.each( [ - [ 'expectShowsAnimatedVisitorsVsDonorsSentenceInMessage' ], - [ 'expectShowsAnimatedVisitorsVsDonorsSentenceInSlideShow' ] - ] )( '%s', async ( testName: string ) => { - await bannerContentAnimatedTextFeatures[ testName ]( getWrapper ); - } ); - - test.each( [ - [ 'expectShowsLiveDateAndTimeInMessage' ], - [ 'expectShowsLiveDateAndTimeInSlideshow' ] - ] )( '%s', async ( testName: string ) => { - await bannerContentDateAndTimeFeatures[ testName ]( getWrapper ); - } ); - } ); - - describe( 'Donation Form Happy Paths', () => { - test.each( [ - [ 'expectMainDonationFormSubmitsWhenSofortIsSelected' ], - [ 'expectMainDonationFormSubmitsWhenYearlyIsSelected' ], - [ 'expectMainDonationFormGoesToUpgrade' ], - [ 'expectUpgradeToYearlyFormSubmitsUpgrade' ], - [ 'expectUpgradeToYearlyFormSubmitsDontUpgrade' ] - ] )( '%s', async ( testName: string ) => { - await donationFormFeatures[ testName ]( getWrapper() ); - } ); - - test.each( [ - [ 'expectMainDonationFormSubmitsWithAddressForDirectDebit' ], - [ 'expectMainDonationFormSubmitsWithAddressForPayPal' ], - [ 'expectUpgradeToYearlyFormSubmitsWithAddressForDirectDebit' ], - [ 'expectUpgradeToYearlyFormSubmitsWithAddressForPayPal' ] - ] )( '%s', async ( testName: string ) => { - await formActionSwitchFeatures[ testName ]( getWrapper() ); - } ); - } ); - - describe( 'Soft Close', () => { - test.each( [ - [ 'expectShowsSoftClose' ], - [ 'expectEmitsSoftCloseCloseEvent' ], - [ 'expectEmitsSoftCloseMaybeLaterEvent' ], - [ 'expectEmitsSoftCloseTimeOutEvent' ], - [ 'expectEmitsBannerContentChangedOnSoftClose' ], - [ 'expectShowsCloseIcon' ], - [ 'expectCloseIconEmitsCloseEvent' ] - ] )( '%s', async ( testName: string ) => { - await softCloseFeatures[ testName ]( getWrapper() ); - } ); - } ); - - describe( 'Soft Close Submit Tracking', () => { - test.each( [ - // this var banner has the softclose feature - [ 'expectEmitsBannerSubmitOnReturnEvent' ], - [ 'expectDoesNotEmitsBannerSubmitOnReturnEventWhenLocalStorageItemIsMissing' ] - ] )( '%s', async ( testName: string ) => { - await softCloseSubmitTrackingFeaturesDesktop[ testName ]( getWrapper(), tracker ); - } ); - } ); - - describe( 'Already Donated', () => { - test.each( [ - [ 'expectFiresMaybeLaterEventOnLinkClick' ] - ] )( '%s', async ( testName: string ) => { - await alreadyDonatedModalFeatures[ testName ]( getWrapper() ); - } ); - } ); - - describe( 'Use of Funds', () => { - test.each( [ - [ 'expectShowsUseOfFunds' ], - [ 'expectHidesUseOfFunds' ] - ] )( '%s', async ( testName: string ) => { - await useOfFundsFeatures[ testName ]( getWrapper() ); - } ); - } ); -} ); diff --git a/test/banners/desktop/C24_WMDE_Desktop_DE_11/components/FallbackBanner.spec.ts b/test/banners/desktop/C24_WMDE_Desktop_DE_11/components/FallbackBanner.spec.ts index bf3e1fe29..c768e7621 100644 --- a/test/banners/desktop/C24_WMDE_Desktop_DE_11/components/FallbackBanner.spec.ts +++ b/test/banners/desktop/C24_WMDE_Desktop_DE_11/components/FallbackBanner.spec.ts @@ -1,6 +1,6 @@ import { afterEach, beforeEach, describe, test, vi } from 'vitest'; import { mount, VueWrapper } from '@vue/test-utils'; -import FallbackBanner from '@banners/desktop/C24_WMDE_Desktop_DE_10/components/FallbackBanner.vue'; +import FallbackBanner from '@banners/desktop/C24_WMDE_Desktop_DE_11/components/FallbackBanner.vue'; import { BannerStates } from '@src/components/BannerConductor/StateMachine/BannerStates'; import { useOfFundsContent } from '@test/banners/useOfFundsContent'; import { newDynamicContent } from '@test/banners/dynamicCampaignContent'; diff --git a/test/features/MainBanner.ts b/test/features/MainBanner.ts index a82288e84..6cb7c7be5 100644 --- a/test/features/MainBanner.ts +++ b/test/features/MainBanner.ts @@ -16,7 +16,24 @@ const expectDoesNotEmitCloseEvent = async ( wrapper: VueWrapper ): Promise< expect( wrapper.emitted( 'bannerClosed' ) ).toBeUndefined(); }; +const expectClosesBannerWhenWindowBecomesSmall = async ( getWrapper: () => VueWrapper ): Promise => { + const wrapper = getWrapper(); + + Object.defineProperty( window, 'innerWidth', { writable: true, configurable: true, value: 800 } ); + window.dispatchEvent( new Event( 'resize' ) ); + + Object.defineProperty( window, 'innerWidth', { writable: true, configurable: true, value: 799 } ); + window.dispatchEvent( new Event( 'resize' ) ); + + expect( wrapper.emitted( 'bannerClosed' ).length ).toBe( 1 ); + expect( wrapper.emitted( 'bannerClosed' )[ 0 ][ 0 ] ).toEqual( new CloseEvent( 'MainBanner', CloseChoices.WindowSizeBelowMin ) ); +}; + export const bannerMainFeatures: Record ) => Promise> = { expectEmitsCloseEvent, expectDoesNotEmitCloseEvent }; + +export const bannerAutoHideFeatures: Record VueWrapper ) => Promise> = { + expectClosesBannerWhenWindowBecomesSmall +};