From 972ad64e7acb48454d6b629d6ca9d056909709ce Mon Sep 17 00:00:00 2001
From: Corinna Hillebrand
Date: Tue, 14 Nov 2023 14:06:11 +0100
Subject: [PATCH 1/4] Archive C23_WMDE_Desktop_DE_12
---
.../C23_WMDE_Desktop_DE_12/banner_ctrl.ts | 67 ++++++++
.../C23_WMDE_Desktop_DE_12/banner_var.ts | 67 ++++++++
.../components/BannerCtrl.vue | 152 ++++++++++++++++++
.../components/BannerVar.vue | 152 ++++++++++++++++++
.../components/MainBanner.vue | 44 +++++
.../content/AlreadyDonatedContent.vue | 14 ++
.../content/BannerSlides.vue | 51 ++++++
.../content/BannerSlidesVar.vue | 51 ++++++
.../content/BannerText.vue | 34 ++++
.../content/BannerTextVar.vue | 34 ++++
.../C23_WMDE_Desktop_DE_12/event_map.ts | 32 ++++
.../C23_WMDE_Desktop_DE_12/form_items.ts | 23 +++
.../C23_WMDE_Desktop_DE_12/messages.ts | 23 +++
.../C23_WMDE_Desktop_DE_12/styles/Banner.scss | 17 ++
.../styles/MainBanner.scss | 45 ++++++
.../C23_WMDE_Desktop_DE_12/styles/styles.scss | 36 +++++
16 files changed, 842 insertions(+)
create mode 100644 archive/desktop/C23_WMDE_Desktop_DE_12/banner_ctrl.ts
create mode 100644 archive/desktop/C23_WMDE_Desktop_DE_12/banner_var.ts
create mode 100644 archive/desktop/C23_WMDE_Desktop_DE_12/components/BannerCtrl.vue
create mode 100644 archive/desktop/C23_WMDE_Desktop_DE_12/components/BannerVar.vue
create mode 100644 archive/desktop/C23_WMDE_Desktop_DE_12/components/MainBanner.vue
create mode 100644 archive/desktop/C23_WMDE_Desktop_DE_12/content/AlreadyDonatedContent.vue
create mode 100644 archive/desktop/C23_WMDE_Desktop_DE_12/content/BannerSlides.vue
create mode 100644 archive/desktop/C23_WMDE_Desktop_DE_12/content/BannerSlidesVar.vue
create mode 100644 archive/desktop/C23_WMDE_Desktop_DE_12/content/BannerText.vue
create mode 100644 archive/desktop/C23_WMDE_Desktop_DE_12/content/BannerTextVar.vue
create mode 100644 archive/desktop/C23_WMDE_Desktop_DE_12/event_map.ts
create mode 100644 archive/desktop/C23_WMDE_Desktop_DE_12/form_items.ts
create mode 100644 archive/desktop/C23_WMDE_Desktop_DE_12/messages.ts
create mode 100644 archive/desktop/C23_WMDE_Desktop_DE_12/styles/Banner.scss
create mode 100644 archive/desktop/C23_WMDE_Desktop_DE_12/styles/MainBanner.scss
create mode 100644 archive/desktop/C23_WMDE_Desktop_DE_12/styles/styles.scss
diff --git a/archive/desktop/C23_WMDE_Desktop_DE_12/banner_ctrl.ts b/archive/desktop/C23_WMDE_Desktop_DE_12/banner_ctrl.ts
new file mode 100644
index 000000000..770b65a85
--- /dev/null
+++ b/archive/desktop/C23_WMDE_Desktop_DE_12/banner_ctrl.ts
@@ -0,0 +1,67 @@
+import { createVueApp } from '@src/createVueApp';
+
+import './styles/styles.scss';
+
+import BannerConductor from '@src/components/BannerConductor/BannerConductor.vue';
+import Banner from './components/BannerCtrl.vue';
+import getBannerDelay from '@src/utils/getBannerDelay';
+import { WindowResizeHandler } from '@src/utils/ResizeHandler';
+import PageWPORG from '@src/page/PageWPORG';
+import { WindowMediaWiki } from '@src/page/MediaWiki/WindowMediaWiki';
+import { SkinFactory } from '@src/page/skin/SkinFactory';
+import { WindowSizeIssueChecker } from '@src/utils/SizeIssueChecker/WindowSizeIssueChecker';
+import TranslationPlugin from '@src/TranslationPlugin';
+import { Translator } from '@src/Translator';
+import DynamicTextPlugin from '@src/DynamicTextPlugin';
+import { LocalImpressionCount } from '@src/utils/LocalImpressionCount';
+import { LegacyTrackerWPORG } from '@src/tracking/LegacyTrackerWPORG';
+import eventMappings from './event_map';
+
+// Locale-specific imports
+import messages from './messages';
+import { LocaleFactoryDe } from '@src/utils/LocaleFactory/LocaleFactoryDe';
+
+// Channel specific form setup
+import { createFormItems } from './form_items';
+import { createFormActions } from '@src/createFormActions';
+
+const localeFactory = new LocaleFactoryDe();
+const translator = new Translator( messages );
+const mediaWiki = new WindowMediaWiki();
+const page = new PageWPORG( mediaWiki, ( new SkinFactory( mediaWiki ) ).getSkin(), new WindowSizeIssueChecker( 800 ) );
+const impressionCount = new LocalImpressionCount( page.getTracking().keyword );
+const tracker = new LegacyTrackerWPORG( mediaWiki, page.getTracking().keyword, eventMappings );
+const remainingImpressions = Math.max( page.getMaxBannerImpressions( 'desktop' ) - impressionCount.overallCountIncremented, 0 );
+
+const app = createVueApp( BannerConductor, {
+ page,
+ bannerConfig: {
+ delay: getBannerDelay( 7500 ),
+ transitionDuration: 1000
+ },
+ bannerProps: {
+ useOfFundsContent: localeFactory.getUseOfFundsLoader().getContent(),
+ remainingImpressions
+ },
+ resizeHandler: new WindowResizeHandler(),
+ banner: Banner,
+ impressionCount
+} );
+
+app.use( TranslationPlugin, translator );
+app.use( DynamicTextPlugin, {
+ campaignParameters: page.getCampaignParameters(),
+ date: new Date(),
+ formatters: localeFactory.getFormatters(),
+ impressionCount,
+ translator
+} );
+
+const currencyFormatter = localeFactory.getCurrencyFormatter();
+
+app.provide( 'currencyFormatter', currencyFormatter );
+app.provide( 'formItems', createFormItems( translator, currencyFormatter.euroAmount.bind( currencyFormatter ) ) );
+app.provide( 'formActions', createFormActions( page.getTracking(), impressionCount, { des: '1' } ) );
+app.provide( 'tracker', tracker );
+
+app.mount( page.getBannerContainer() );
diff --git a/archive/desktop/C23_WMDE_Desktop_DE_12/banner_var.ts b/archive/desktop/C23_WMDE_Desktop_DE_12/banner_var.ts
new file mode 100644
index 000000000..d4798085c
--- /dev/null
+++ b/archive/desktop/C23_WMDE_Desktop_DE_12/banner_var.ts
@@ -0,0 +1,67 @@
+import { createVueApp } from '@src/createVueApp';
+
+import './styles/styles.scss';
+
+import BannerConductor from '@src/components/BannerConductor/BannerConductor.vue';
+import Banner from './components/BannerVar.vue';
+import getBannerDelay from '@src/utils/getBannerDelay';
+import { WindowResizeHandler } from '@src/utils/ResizeHandler';
+import PageWPORG from '@src/page/PageWPORG';
+import { WindowMediaWiki } from '@src/page/MediaWiki/WindowMediaWiki';
+import { SkinFactory } from '@src/page/skin/SkinFactory';
+import { WindowSizeIssueChecker } from '@src/utils/SizeIssueChecker/WindowSizeIssueChecker';
+import TranslationPlugin from '@src/TranslationPlugin';
+import { Translator } from '@src/Translator';
+import DynamicTextPlugin from '@src/DynamicTextPlugin';
+import { LocalImpressionCount } from '@src/utils/LocalImpressionCount';
+import { LegacyTrackerWPORG } from '@src/tracking/LegacyTrackerWPORG';
+import eventMappings from './event_map';
+
+// Locale-specific imports
+import messages from './messages';
+import { LocaleFactoryDe } from '@src/utils/LocaleFactory/LocaleFactoryDe';
+
+// Channel specific form setup
+import { createFormItems } from './form_items';
+import { createFormActions } from '@src/createFormActions';
+
+const localeFactory = new LocaleFactoryDe();
+const translator = new Translator( messages );
+const mediaWiki = new WindowMediaWiki();
+const page = new PageWPORG( mediaWiki, ( new SkinFactory( mediaWiki ) ).getSkin(), new WindowSizeIssueChecker( 800 ) );
+const impressionCount = new LocalImpressionCount( page.getTracking().keyword );
+const tracker = new LegacyTrackerWPORG( mediaWiki, page.getTracking().keyword, eventMappings );
+const remainingImpressions = Math.max( page.getMaxBannerImpressions( 'desktop' ) - impressionCount.overallCountIncremented, 0 );
+
+const app = createVueApp( BannerConductor, {
+ page,
+ bannerConfig: {
+ delay: getBannerDelay( 7500 ),
+ transitionDuration: 1000
+ },
+ bannerProps: {
+ useOfFundsContent: localeFactory.getUseOfFundsLoader().getContent(),
+ remainingImpressions
+ },
+ resizeHandler: new WindowResizeHandler(),
+ banner: Banner,
+ impressionCount
+} );
+
+app.use( TranslationPlugin, translator );
+app.use( DynamicTextPlugin, {
+ campaignParameters: page.getCampaignParameters(),
+ date: new Date(),
+ formatters: localeFactory.getFormatters(),
+ impressionCount,
+ translator
+} );
+
+const currencyFormatter = localeFactory.getCurrencyFormatter();
+
+app.provide( 'currencyFormatter', currencyFormatter );
+app.provide( 'formItems', createFormItems( translator, currencyFormatter.euroAmount.bind( currencyFormatter ) ) );
+app.provide( 'formActions', createFormActions( page.getTracking(), impressionCount, { des: '1' } ) );
+app.provide( 'tracker', tracker );
+
+app.mount( page.getBannerContainer() );
diff --git a/archive/desktop/C23_WMDE_Desktop_DE_12/components/BannerCtrl.vue b/archive/desktop/C23_WMDE_Desktop_DE_12/components/BannerCtrl.vue
new file mode 100644
index 000000000..6166fa51c
--- /dev/null
+++ b/archive/desktop/C23_WMDE_Desktop_DE_12/components/BannerCtrl.vue
@@ -0,0 +1,152 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
onClose( 'SoftClose', CloseChoices.Close )"
+ @maybeLater="() => onClose( 'SoftClose', CloseChoices.MaybeLater )"
+ @timeOutClose="() => onClose( 'SoftClose', CloseChoices.TimeOut )"
+ />
+
+
+
+ onClose( 'AlreadyDonatedModal', CloseChoices.NoMoreBannersForCampaign )"
+ @maybeLater="() => onClose( 'AlreadyDonatedModal', CloseChoices.MaybeLater )"
+ >
+
+
+
+
+
+
+
+
diff --git a/archive/desktop/C23_WMDE_Desktop_DE_12/components/BannerVar.vue b/archive/desktop/C23_WMDE_Desktop_DE_12/components/BannerVar.vue
new file mode 100644
index 000000000..f2028754c
--- /dev/null
+++ b/archive/desktop/C23_WMDE_Desktop_DE_12/components/BannerVar.vue
@@ -0,0 +1,152 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
onClose( 'SoftClose', CloseChoices.Close )"
+ @maybeLater="() => onClose( 'SoftClose', CloseChoices.MaybeLater )"
+ @timeOutClose="() => onClose( 'SoftClose', CloseChoices.TimeOut )"
+ />
+
+
+
+ onClose( 'AlreadyDonatedModal', CloseChoices.NoMoreBannersForCampaign )"
+ @maybeLater="() => onClose( 'AlreadyDonatedModal', CloseChoices.MaybeLater )"
+ >
+
+
+
+
+
+
+
+
diff --git a/archive/desktop/C23_WMDE_Desktop_DE_12/components/MainBanner.vue b/archive/desktop/C23_WMDE_Desktop_DE_12/components/MainBanner.vue
new file mode 100644
index 000000000..ab097bf67
--- /dev/null
+++ b/archive/desktop/C23_WMDE_Desktop_DE_12/components/MainBanner.vue
@@ -0,0 +1,44 @@
+tart
+
+
+
+
diff --git a/archive/desktop/C23_WMDE_Desktop_DE_12/content/AlreadyDonatedContent.vue b/archive/desktop/C23_WMDE_Desktop_DE_12/content/AlreadyDonatedContent.vue
new file mode 100644
index 000000000..030127d52
--- /dev/null
+++ b/archive/desktop/C23_WMDE_Desktop_DE_12/content/AlreadyDonatedContent.vue
@@ -0,0 +1,14 @@
+
+
+
Vielen Dank für Ihre Unterstützung
+
+ Es freut uns, dass Sie uns bereits unterstützt haben oder regelmäßig unterstützen. Ohne Sie wäre die
+ Finanzierung unserer Projekte nicht möglich.
+
+
+ Falls Sie sich eine (weitere) Spende vorstellen können, dann klicken Sie "Vielleicht später". Falls
+ nicht, klicken Sie: "Fürs Erste reicht es". In diesem Fall wird ein Cookie in Ihrem Browser gesetzt,
+ der die Anzeige der Banner vorerst verhindert.
+
+
+
diff --git a/archive/desktop/C23_WMDE_Desktop_DE_12/content/BannerSlides.vue b/archive/desktop/C23_WMDE_Desktop_DE_12/content/BannerSlides.vue
new file mode 100644
index 000000000..1bda195d8
--- /dev/null
+++ b/archive/desktop/C23_WMDE_Desktop_DE_12/content/BannerSlides.vue
@@ -0,0 +1,51 @@
+
+
+
+ An alle, die Wikipedia in Deutschland nutzen
+
+
+ Vielleicht kommen wir gerade ungelegen, aber dennoch: Klicken Sie jetzt bitte nicht weg! Am
+ heutigen {{ currentDayName }}, den {{ currentDate }}, bitten wir Sie bescheiden, die Unabhängigkeit
+ von Wikipedia zu unterstützen.
+
+
+
+
+ {{ campaignDaySentence }}
+
+
+
+
+ Die meisten Menschen spenden, weil sie Wikipedia nützlich finden. Die durchschnittliche Spende
+ beträgt 22,25 €, doch bereits 5 € helfen uns weiter.
+
+
+
+
+ Hat Wikipedia Ihnen in diesem Jahr Wissen im Wert einer Tasse Kaffee geschenkt? Dann entscheiden
+ Sie sich, eine der seltenen Ausnahmen zu sein, und geben Sie etwas zurück. Vielen Dank!
+
+
+
+
+
diff --git a/archive/desktop/C23_WMDE_Desktop_DE_12/content/BannerSlidesVar.vue b/archive/desktop/C23_WMDE_Desktop_DE_12/content/BannerSlidesVar.vue
new file mode 100644
index 000000000..74950ba14
--- /dev/null
+++ b/archive/desktop/C23_WMDE_Desktop_DE_12/content/BannerSlidesVar.vue
@@ -0,0 +1,51 @@
+
+
+
+ An alle, die Wikipedia in Deutschland nutzen
+
+
+ Vielleicht kommen wir gerade ungelegen, aber dennoch: Klicken Sie jetzt bitte nicht weg! Am
+ heutigen {{ currentDayName }}, den {{ currentDate }}, bitten wir Sie, die Unabhängigkeit
+ von Wikipedia zu unterstützen.
+
+
+
+
+ {{ campaignDaySentence }}
+
+
+
+
+ Die meisten Menschen spenden, weil sie Wikipedia nützlich finden. Die durchschnittliche Spende
+ beträgt 22,25 €, doch bereits 5 € helfen uns weiter.
+
+
+
+
+ Hat Wikipedia Ihnen in diesem Jahr Wissen im Wert einer Tasse Kaffee geschenkt? Dann entscheiden
+ Sie sich, eine der seltenen Ausnahmen zu sein, und geben Sie etwas zurück. Vielen Dank!
+
+
+
+
+
diff --git a/archive/desktop/C23_WMDE_Desktop_DE_12/content/BannerText.vue b/archive/desktop/C23_WMDE_Desktop_DE_12/content/BannerText.vue
new file mode 100644
index 000000000..388cdb47a
--- /dev/null
+++ b/archive/desktop/C23_WMDE_Desktop_DE_12/content/BannerText.vue
@@ -0,0 +1,34 @@
+
+
+
+
+
+ An alle, die Wikipedia in Deutschland nutzen
+
+
+ Vielleicht kommen wir gerade ungelegen, aber dennoch: Klicken Sie jetzt bitte nicht weg! Am
+ heutigen {{ currentDayName }}, den {{ currentDate }}, bitten wir Sie bescheiden, die Unabhängigkeit
+ von Wikipedia zu unterstützen. {{ campaignDaySentence }} Die meisten
+ Menschen spenden, weil sie Wikipedia nützlich finden. Die durchschnittliche Spende beträgt 22,25 €,
+ doch bereits 5 € helfen uns weiter. Hat Wikipedia Ihnen in diesem Jahr Wissen im Wert einer Tasse
+ Kaffee geschenkt? Dann entscheiden Sie sich, eine der seltenen Ausnahmen zu sein, und geben Sie etwas
+ zurück. Vielen Dank!
+
+
+
+
+
+
diff --git a/archive/desktop/C23_WMDE_Desktop_DE_12/content/BannerTextVar.vue b/archive/desktop/C23_WMDE_Desktop_DE_12/content/BannerTextVar.vue
new file mode 100644
index 000000000..a11df4d94
--- /dev/null
+++ b/archive/desktop/C23_WMDE_Desktop_DE_12/content/BannerTextVar.vue
@@ -0,0 +1,34 @@
+
+
+
+
+
+ An alle, die Wikipedia in Deutschland nutzen
+
+
+ Vielleicht kommen wir gerade ungelegen, aber dennoch: Klicken Sie jetzt bitte nicht weg! Am
+ heutigen {{ currentDayName }}, den {{ currentDate }}, bitten wir Sie, die Unabhängigkeit
+ von Wikipedia zu unterstützen. {{ campaignDaySentence }} Die meisten
+ Menschen spenden, weil sie Wikipedia nützlich finden. Die durchschnittliche Spende beträgt 22,25 €,
+ doch bereits 5 € helfen uns weiter. Hat Wikipedia Ihnen in diesem Jahr Wissen im Wert einer Tasse
+ Kaffee geschenkt? Dann entscheiden Sie sich, eine der seltenen Ausnahmen zu sein, und geben Sie etwas
+ zurück. Vielen Dank!
+
+
+
+
+
+
diff --git a/archive/desktop/C23_WMDE_Desktop_DE_12/event_map.ts b/archive/desktop/C23_WMDE_Desktop_DE_12/event_map.ts
new file mode 100644
index 000000000..b4f7e49dd
--- /dev/null
+++ b/archive/desktop/C23_WMDE_Desktop_DE_12/event_map.ts
@@ -0,0 +1,32 @@
+import { TrackingEventConverterFactory } from '@src/tracking/LegacyTrackerWPORG';
+import { WMDELegacyBannerEvent } from '@src/tracking/WPORG/WMDELegacyBannerEvent';
+import { WMDESizeIssueEvent } from '@src/tracking/WPORG/WMDEBannerSizeIssue';
+import { BannerSubmitEvent } from '@src/tracking/events/BannerSubmitEvent';
+import { FormStepShownEvent } from '@src/tracking/events/FormStepShownEvent';
+import { mapFormStepShownEvent } from '@src/tracking/LegacyEventTracking/mapFormStepShownEvent';
+import { CustomAmountChangedEvent } from '@src/tracking/events/CustomAmountChangedEvent';
+import { CloseEvent } from '@src/tracking/events/CloseEvent';
+import { mapCloseEvent } from '@src/tracking/LegacyEventTracking/mapCloseEvent';
+import { NotShownEvent } from '@src/tracking/events/NotShownEvent';
+import { mapNotShownEvent } from '@src/tracking/LegacyEventTracking/mapNotShownEvent';
+import { createViewportInfo } from '@src/tracking/LegacyEventTracking/createViewportInfo';
+import { AlreadyDonatedShownEvent } from '@src/tracking/events/AlreadyDonatedShownEvent';
+
+export default new Map( [
+ [ CloseEvent.EVENT_NAME, mapCloseEvent ],
+ [ FormStepShownEvent.EVENT_NAME, mapFormStepShownEvent ],
+ [ CustomAmountChangedEvent.EVENT_NAME,
+ ( e: CustomAmountChangedEvent ): WMDELegacyBannerEvent =>
+ new WMDELegacyBannerEvent( e.userChoice + '-amount', 1 )
+ ],
+ [ AlreadyDonatedShownEvent.EVENT_NAME, ( e: AlreadyDonatedShownEvent ): WMDELegacyBannerEvent => new WMDELegacyBannerEvent( e.eventName, 1 ) ],
+ [ NotShownEvent.EVENT_NAME, mapNotShownEvent ],
+ [ BannerSubmitEvent.EVENT_NAME, ( e: BannerSubmitEvent ): WMDESizeIssueEvent => {
+ switch ( e.feature ) {
+ case 'UpgradeToYearlyForm':
+ return new WMDESizeIssueEvent( `submit-${e.userChoice}`, createViewportInfo(), 1 );
+ default:
+ return new WMDESizeIssueEvent( `submit`, createViewportInfo(), 1 );
+ }
+ } ]
+] );
diff --git a/archive/desktop/C23_WMDE_Desktop_DE_12/form_items.ts b/archive/desktop/C23_WMDE_Desktop_DE_12/form_items.ts
new file mode 100644
index 000000000..b70650d19
--- /dev/null
+++ b/archive/desktop/C23_WMDE_Desktop_DE_12/form_items.ts
@@ -0,0 +1,23 @@
+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,
+ Intervals.QUARTERLY,
+ Intervals.YEARLY
+ )
+ .setAmounts( 5, 10, 20, 25, 50, 100 )
+ .setPaymentMethods(
+ PaymentMethods.PAYPAL,
+ PaymentMethods.BANK_TRANSFER,
+ PaymentMethods.CREDIT_CARD,
+ PaymentMethods.DIRECT_DEBIT
+ ).getItems();
+}
diff --git a/archive/desktop/C23_WMDE_Desktop_DE_12/messages.ts b/archive/desktop/C23_WMDE_Desktop_DE_12/messages.ts
new file mode 100644
index 000000000..cef9a830d
--- /dev/null
+++ b/archive/desktop/C23_WMDE_Desktop_DE_12/messages.ts
@@ -0,0 +1,23 @@
+import CustomAmountFormDe from '@src/components/DonationForm/Forms/messages/CustomAmountForm.de';
+import DynamicCampaignTextDe from '@src/utils/DynamicContent/messages/DynamicCampaignText.de';
+import { TranslationMessages } from '@src/Translator';
+import UpgradeToYearlyDe from '@src/components/DonationForm/Forms/messages/UpgradeToYearly.de';
+import SoftCloseDe from '@src/components/SoftClose/messages/SoftClose.de';
+import AddressFormDe from '@src/components/DonationForm/Forms/messages/AddressForm.de';
+import FooterDe from '@src/components/Footer/messages/Footer.de';
+import MainDonationFormDe from '@src/components/DonationForm/Forms/messages/MainDonationForm.de';
+import AlreadyDonatedModal from '@src/components/AlreadyDonatedModal/translations/AlreadyDonatedModal.de';
+
+const messages: TranslationMessages = {
+ ...CustomAmountFormDe,
+ ...DynamicCampaignTextDe,
+ ...UpgradeToYearlyDe,
+ ...SoftCloseDe,
+ ...AddressFormDe,
+ ...FooterDe,
+ ...MainDonationFormDe,
+ ...AlreadyDonatedModal,
+ 'already-donated-go-away-button': 'Fürs Erste reicht es'
+};
+
+export default messages;
diff --git a/archive/desktop/C23_WMDE_Desktop_DE_12/styles/Banner.scss b/archive/desktop/C23_WMDE_Desktop_DE_12/styles/Banner.scss
new file mode 100644
index 000000000..06e30756a
--- /dev/null
+++ b/archive/desktop/C23_WMDE_Desktop_DE_12/styles/Banner.scss
@@ -0,0 +1,17 @@
+@use 'src/themes/Treedip/variables/fonts';
+@use 'src/themes/Treedip/variables/colors';
+
+.wmde-banner {
+ &-wrapper {
+ font-size: 14px;
+ font-family: fonts.$ui;
+ box-shadow: 0 3px 0.6em rgba( 60 60 60 / 40% );
+ background-color: colors.$white;
+ }
+
+ &--closed {
+ .wmde-banner-wrapper {
+ display: none;
+ }
+ }
+}
diff --git a/archive/desktop/C23_WMDE_Desktop_DE_12/styles/MainBanner.scss b/archive/desktop/C23_WMDE_Desktop_DE_12/styles/MainBanner.scss
new file mode 100644
index 000000000..c328cbca9
--- /dev/null
+++ b/archive/desktop/C23_WMDE_Desktop_DE_12/styles/MainBanner.scss
@@ -0,0 +1,45 @@
+@use 'src/themes/Treedip/variables/colors';
+
+$banner-height: 357px !default;
+$form-width: 300px !default;
+
+.wmde-banner {
+ &-main {
+ min-height: $banner-height;
+ display: flex;
+ flex-direction: column;
+ padding: 12px 24px 0;
+ }
+
+ &-content {
+ display: flex;
+ flex-direction: row;
+ flex-grow: 1;
+ }
+
+ &-message {
+ padding: 0 15px;
+ }
+
+ &-column-left {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ flex: 1 1 auto;
+ margin-bottom: 0;
+ overflow-y: hidden;
+ margin-right: 30px;
+ padding: 0 0 10px;
+ border: 5px solid colors.$primary;
+ border-radius: 9px;
+ }
+
+ &-column-right {
+ order: 2;
+ flex: 0 0 $form-width;
+ display: flex;
+ flex-direction: column;
+ width: $form-width;
+ padding: 10px 0;
+ }
+}
diff --git a/archive/desktop/C23_WMDE_Desktop_DE_12/styles/styles.scss b/archive/desktop/C23_WMDE_Desktop_DE_12/styles/styles.scss
new file mode 100644
index 000000000..6cd8308ba
--- /dev/null
+++ b/archive/desktop/C23_WMDE_Desktop_DE_12/styles/styles.scss
@@ -0,0 +1,36 @@
+// This is the file where we import the theme-specific component styles
+$font: 'Iowan Old Style', 'Sitka Text', 'Cambria', serif;
+
+@use 'src/components/BannerConductor/banner-transition';
+@use 'Banner';
+@use 'MainBanner' with (
+ $banner-height: 357px,
+ $form-width: 300px
+);
+@use 'src/themes/UseOfFunds/UseOfFunds';
+@use 'src/themes/Treedip/defaults';
+@use 'src/themes/Treedip/ButtonClose/ButtonClose';
+@use 'src/themes/Treedip/ProgressBar/ProgressBar' with (
+ $progress-bar-margin: 0 15px
+);
+@use 'src/themes/Treedip/DonationForm/DonationForm';
+@use 'src/themes/Treedip/DonationForm/MultiStepDonation';
+@use 'src/themes/Treedip/DonationForm/SubComponents/SelectGroup';
+@use 'src/themes/Treedip/DonationForm/SubComponents/SelectGroupRadios';
+@use 'src/themes/Treedip/DonationForm/SubComponents/SelectCustomAmountRadio';
+@use 'src/themes/Treedip/DonationForm/SubComponents/SmsBox';
+@use 'src/themes/Treedip/DonationForm/Forms/MainDonationForm';
+@use 'src/themes/Treedip/DonationForm/Forms/UpgradeToYearlyForm';
+@use 'src/themes/Treedip/DonationForm/Forms/CustomAmountForm';
+@use 'src/themes/Treedip/Footer/FooterAlreadyDonated' with (
+ $right-column-width: 300px
+);
+@use 'src/themes/Treedip/Footer/SelectionInput';
+@use 'src/themes/Treedip/Message/Message' with (
+ $font: $font
+);
+@use 'src/themes/Treedip/Slider/KeenSlider' with (
+ $font: $font
+);
+@use 'src/themes/Treedip/SoftClose/SoftClose';
+@use 'src/themes/Treedip/AlreadyDonatedModal/AlreadyDonatedModal';
From d202be00385fd78ef9a19e880b18701923e22f46 Mon Sep 17 00:00:00 2001
From: Corinna Hillebrand
Date: Tue, 14 Nov 2023 17:21:41 +0100
Subject: [PATCH 2/4] Prepare campaign for C23_WMDE_Desktop_DE_13
- based on ctrl 12
- adds close button for softclose for both banners
- the new x close button prevents banners for 7 days
- clicking on the maybelater button on alreadydonated hides banners for 7 days
https://phabricator.wikimedia.org/T351199
---
banners/desktop/components/BannerCtrl.vue | 5 +-
banners/desktop/components/BannerVar.vue | 47 ++++++++--
.../components/SoftCloseWithXButton.vue | 86 +++++++++++++++++++
banners/desktop/content/BannerSlidesVar.vue | 51 -----------
banners/desktop/content/BannerTextVar.vue | 34 --------
banners/desktop/messages.ts | 2 +-
.../SoftCloseWithXButtonOverwrites.scss | 16 ++++
banners/desktop/styles/styles.scss | 1 +
campaign_info.toml | 14 +--
.../Forms/messages/UpgradeToYearly.de.ts | 2 +-
src/components/SoftClose/SoftClose.vue | 2 +-
src/domain/CloseChoices.ts | 2 +-
.../dev/CampaignParameterOverride.ts | 4 +-
src/tracking/LegacyCloseSources.ts | 3 +
.../LegacyEventTracking/mapCloseEvent.ts | 9 ++
src/tracking/TrackingEvent.ts | 1 +
src/tracking/events/UpgradeToMonthlyEvent.ts | 14 +++
17 files changed, 184 insertions(+), 109 deletions(-)
create mode 100644 banners/desktop/components/SoftCloseWithXButton.vue
delete mode 100644 banners/desktop/content/BannerSlidesVar.vue
delete mode 100644 banners/desktop/content/BannerTextVar.vue
create mode 100644 banners/desktop/styles/SoftCloseWithXButtonOverwrites.scss
create mode 100644 src/tracking/events/UpgradeToMonthlyEvent.ts
diff --git a/banners/desktop/components/BannerCtrl.vue b/banners/desktop/components/BannerCtrl.vue
index 6166fa51c..2fdbc79cd 100644
--- a/banners/desktop/components/BannerCtrl.vue
+++ b/banners/desktop/components/BannerCtrl.vue
@@ -55,6 +55,7 @@
@close="() => onClose( 'SoftClose', CloseChoices.Close )"
@maybeLater="() => onClose( 'SoftClose', CloseChoices.MaybeLater )"
@timeOutClose="() => onClose( 'SoftClose', CloseChoices.TimeOut )"
+ @maybeLater7Days="() => onClose('SoftClose', CloseChoices.Close)"
/>
onClose( 'AlreadyDonatedModal', CloseChoices.NoMoreBannersForCampaign )"
- @maybeLater="() => onClose( 'AlreadyDonatedModal', CloseChoices.MaybeLater )"
+ @maybeLater="() => onClose( 'AlreadyDonatedModal', CloseChoices.Close )"
>
@@ -80,7 +81,7 @@
import { BannerStates } from '@src/components/BannerConductor/StateMachine/BannerStates';
import { ref, watch } from 'vue';
import { UseOfFundsContent as useOfFundsContentInterface } from '@src/domain/UseOfFunds/UseOfFundsContent';
-import SoftClose from '@src/components/SoftClose/SoftClose.vue';
+import SoftClose from './SoftCloseWithXButton.vue';
import MainBanner from './MainBanner.vue';
import FundsModal from '@src/components/UseOfFunds/FundsModal.vue';
import BannerText from '../content/BannerText.vue';
diff --git a/banners/desktop/components/BannerVar.vue b/banners/desktop/components/BannerVar.vue
index f2028754c..d5a6f88d1 100644
--- a/banners/desktop/components/BannerVar.vue
+++ b/banners/desktop/components/BannerVar.vue
@@ -38,6 +38,10 @@
+
+
+
+
@@ -55,6 +59,7 @@
@close="() => onClose( 'SoftClose', CloseChoices.Close )"
@maybeLater="() => onClose( 'SoftClose', CloseChoices.MaybeLater )"
@timeOutClose="() => onClose( 'SoftClose', CloseChoices.TimeOut )"
+ @maybeLater7Days="() => onClose('SoftClose', CloseChoices.Close)"
/>
onClose( 'AlreadyDonatedModal', CloseChoices.NoMoreBannersForCampaign )"
- @maybeLater="() => onClose( 'AlreadyDonatedModal', CloseChoices.MaybeLater )"
+ @maybeLater="() => onClose( 'AlreadyDonatedModal', CloseChoices.Close )"
>
@@ -78,17 +83,18 @@
diff --git a/banners/desktop/content/BannerSlidesVar.vue b/banners/desktop/content/BannerSlidesVar.vue
deleted file mode 100644
index 74950ba14..000000000
--- a/banners/desktop/content/BannerSlidesVar.vue
+++ /dev/null
@@ -1,51 +0,0 @@
-
-
-
- An alle, die Wikipedia in Deutschland nutzen
-
-
- Vielleicht kommen wir gerade ungelegen, aber dennoch: Klicken Sie jetzt bitte nicht weg! Am
- heutigen {{ currentDayName }}, den {{ currentDate }}, bitten wir Sie, die Unabhängigkeit
- von Wikipedia zu unterstützen.
-
-
-
-
- {{ campaignDaySentence }}
-
-
-
-
- Die meisten Menschen spenden, weil sie Wikipedia nützlich finden. Die durchschnittliche Spende
- beträgt 22,25 €, doch bereits 5 € helfen uns weiter.
-
-
-
-
- Hat Wikipedia Ihnen in diesem Jahr Wissen im Wert einer Tasse Kaffee geschenkt? Dann entscheiden
- Sie sich, eine der seltenen Ausnahmen zu sein, und geben Sie etwas zurück. Vielen Dank!
-
-
-
-
-
diff --git a/banners/desktop/content/BannerTextVar.vue b/banners/desktop/content/BannerTextVar.vue
deleted file mode 100644
index a11df4d94..000000000
--- a/banners/desktop/content/BannerTextVar.vue
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
-
- An alle, die Wikipedia in Deutschland nutzen
-
-
- Vielleicht kommen wir gerade ungelegen, aber dennoch: Klicken Sie jetzt bitte nicht weg! Am
- heutigen {{ currentDayName }}, den {{ currentDate }}, bitten wir Sie, die Unabhängigkeit
- von Wikipedia zu unterstützen. {{ campaignDaySentence }} Die meisten
- Menschen spenden, weil sie Wikipedia nützlich finden. Die durchschnittliche Spende beträgt 22,25 €,
- doch bereits 5 € helfen uns weiter. Hat Wikipedia Ihnen in diesem Jahr Wissen im Wert einer Tasse
- Kaffee geschenkt? Dann entscheiden Sie sich, eine der seltenen Ausnahmen zu sein, und geben Sie etwas
- zurück. Vielen Dank!
-
-
-
-
-
-
diff --git a/banners/desktop/messages.ts b/banners/desktop/messages.ts
index cef9a830d..2e2c04350 100644
--- a/banners/desktop/messages.ts
+++ b/banners/desktop/messages.ts
@@ -17,7 +17,7 @@ const messages: TranslationMessages = {
...FooterDe,
...MainDonationFormDe,
...AlreadyDonatedModal,
- 'already-donated-go-away-button': 'Fürs Erste reicht es'
+ 'already-donated-go-away-button': 'Im Moment nicht'
};
export default messages;
diff --git a/banners/desktop/styles/SoftCloseWithXButtonOverwrites.scss b/banners/desktop/styles/SoftCloseWithXButtonOverwrites.scss
new file mode 100644
index 000000000..949c749bc
--- /dev/null
+++ b/banners/desktop/styles/SoftCloseWithXButtonOverwrites.scss
@@ -0,0 +1,16 @@
+@use 'src/themes/Treedip/variables/colors';
+@use 'src/themes/Treedip/variables/breakpoints';
+@use 'src/themes/Treedip/variables/fonts';
+
+.wmde-banner {
+
+ &-soft-close {
+ &-columns {
+ padding-right: 50px;
+
+ @include breakpoints.large-up {
+ padding-right: 50px;
+ }
+ }
+ }
+}
diff --git a/banners/desktop/styles/styles.scss b/banners/desktop/styles/styles.scss
index c6a93d259..e8f805658 100644
--- a/banners/desktop/styles/styles.scss
+++ b/banners/desktop/styles/styles.scss
@@ -28,4 +28,5 @@
@use 'src/themes/Treedip/Message/Message';
@use 'src/themes/Treedip/Slider/KeenSlider';
@use 'src/themes/Treedip/SoftClose/SoftClose';
+@use './SoftCloseWithXButtonOverwrites';
@use 'src/themes/Treedip/AlreadyDonatedModal/AlreadyDonatedModal';
diff --git a/campaign_info.toml b/campaign_info.toml
index 776b7e7fd..c604c35fb 100644
--- a/campaign_info.toml
+++ b/campaign_info.toml
@@ -6,9 +6,9 @@
[desktop]
name = "Desktop"
icon = "desktop"
-campaign = "C23_WMDE_Desktop_DE_12"
-description = "based on VAR of test 10, variant contains a text change"
-campaign_tracking = "12-ba-231113"
+campaign = "C23_WMDE_Desktop_DE_13"
+description = "based on ctrl of test 12, variant asks for monthly donations"
+campaign_tracking = "13-ba-231116"
preview_link = "/wiki/Wikipedia:Hauptseite?devbanner={{banner}}&banner=B22_WMDE_local_prototype"
preview_url = 'https://de.wikipedia.org/wiki/Wikipedia:Hauptseite?banner={{banner}}&devMode'
wrapper_template = "wikipedia_org"
@@ -17,13 +17,13 @@ use_of_funds_source = "MediaWiki:WMDE_Fundraising/UseOfFunds_2023_DE"
# Banners of the campaign, key after "banners" can be anything
[desktop.banners.ctrl]
filename = "./banners/desktop/banner_ctrl.ts"
-pagename = "B23_WMDE_Desktop_DE_12_ctrl"
-tracking = "org-12-231113-ctrl"
+pagename = "B23_WMDE_Desktop_DE_13_ctrl"
+tracking = "org-13-231116-ctrl"
[desktop.banners.var]
filename = "./banners/desktop/banner_var.ts"
-pagename = "B23_WMDE_Desktop_DE_12_var"
-tracking = "org-12-231113-var"
+pagename = "B23_WMDE_Desktop_DE_13_var"
+tracking = "org-13-231116-var"
[desktop.test_matrix]
platform = ["edge", "firefox_win10", "chrome_win10", "safari", "firefox_macos", "chrome_macos", "firefox_linux", "chrome_linux"]
diff --git a/src/components/DonationForm/Forms/messages/UpgradeToYearly.de.ts b/src/components/DonationForm/Forms/messages/UpgradeToYearly.de.ts
index 493e53383..7da77acb8 100644
--- a/src/components/DonationForm/Forms/messages/UpgradeToYearly.de.ts
+++ b/src/components/DonationForm/Forms/messages/UpgradeToYearly.de.ts
@@ -3,7 +3,7 @@ import { TranslationMessages } from '@src/Translator';
const Translations: TranslationMessages = {
'upgrade-to-yearly-header': 'Könnten Sie auch {{amount}} jährlich spenden?',
'upgrade-to-yearly-copy': 'Jedes Jahr sind wir auf die Unterstützung von Menschen wie Ihnen angewiesen.' +
- ' Jährliche Spenden helfen uns nachhaltig und ermöglichen längfristige Weiterentwicklungen.',
+ ' Jährliche Spenden helfen uns nachhaltig und ermöglichen langfristige Weiterentwicklungen.',
'upgrade-to-yearly-no': 'Nein, ich möchte einmalig {{amount}} spenden.',
'upgrade-to-yearly-yes': 'Ja, ich möchte {{amount}} jährlich spenden.',
'upgrade-to-yearly-link': 'Ja, ich möchte jährlich spenden, aber einen anderen Betrag.',
diff --git a/src/components/SoftClose/SoftClose.vue b/src/components/SoftClose/SoftClose.vue
index 50a647182..f2e6720d3 100644
--- a/src/components/SoftClose/SoftClose.vue
+++ b/src/components/SoftClose/SoftClose.vue
@@ -45,7 +45,7 @@ interface Props {
}
const props = withDefaults( defineProps(), {
- secondsTotal: 15
+ secondsTotal: 35
} );
const timer = ref( 0 );
diff --git a/src/domain/CloseChoices.ts b/src/domain/CloseChoices.ts
index 91940924a..8146a2026 100644
--- a/src/domain/CloseChoices.ts
+++ b/src/domain/CloseChoices.ts
@@ -8,5 +8,5 @@ export enum CloseChoices {
/** user ignored soft close timer */
TimeOut = 'time-out',
/** user clicked a go away for campaign button */
- NoMoreBannersForCampaign = 'no-more-banners'
+ NoMoreBannersForCampaign = 'no-more-banners',
}
diff --git a/src/environment/dev/CampaignParameterOverride.ts b/src/environment/dev/CampaignParameterOverride.ts
index 9dfaeaa16..db372c8c0 100644
--- a/src/environment/dev/CampaignParameterOverride.ts
+++ b/src/environment/dev/CampaignParameterOverride.ts
@@ -15,12 +15,12 @@ import { CampaignParameters } from '@src/domain/CampaignParameters';
export function getCampaignParameterOverride( campaignParameters: CampaignParameters ): CampaignParameters {
return {
...campaignParameters,
- startDate: '2023-03-20',
+ startDate: '2023-10-30',
millionImpressionsPerDay: 10,
campaignProjection: {
...campaignParameters.campaignProjection,
donationCountBase: 100,
- updatedAt: '2023-03-20'
+ updatedAt: '2023-10-30'
}
};
}
diff --git a/src/tracking/LegacyCloseSources.ts b/src/tracking/LegacyCloseSources.ts
index 8952e1d50..16d9da1a8 100644
--- a/src/tracking/LegacyCloseSources.ts
+++ b/src/tracking/LegacyCloseSources.ts
@@ -32,4 +32,7 @@ export enum LegacyCloseSources {
/** user pressed "maybe later" option on the already donated modal */
AlreadyDonatedMaybeLater = 'already-donated-maybe-later',
+
+ /** user pressed the 'x' close button on the softclose banner */
+ SoftCloseXButton = 'softclose-x-button',
}
diff --git a/src/tracking/LegacyEventTracking/mapCloseEvent.ts b/src/tracking/LegacyEventTracking/mapCloseEvent.ts
index 8feb34e3c..679409730 100644
--- a/src/tracking/LegacyEventTracking/mapCloseEvent.ts
+++ b/src/tracking/LegacyEventTracking/mapCloseEvent.ts
@@ -8,6 +8,7 @@ const closeSourceToLegacyEventName = new Map( [
[ LegacyCloseSources.AlreadyDonatedGoAway, 'banner-closed-already-donated' ],
[ LegacyCloseSources.AlreadyDonatedMaybeLater, 'banner-closed-already-donated-maybelater' ],
[ LegacyCloseSources.SoftCloseAlreadyDonated, 'banner-closed-soft-close-already-donated' ],
+ [ LegacyCloseSources.SoftCloseXButton, 'banner-closed-softclose-closebutton' ],
[ LegacyCloseSources.FullPageBanner, 'banner-closed-full' ],
[ LegacyCloseSources.MaybeLater, 'banner-closed-maybelater' ],
[ LegacyCloseSources.TimeOut, 'micro-banner-ignored' ]
@@ -36,6 +37,14 @@ export function mapCloseEvent( event: CloseEvent ): WMDELegacyBannerEvent {
if ( event.userChoice === CloseChoices.NoMoreBannersForCampaign ) {
return new WMDELegacyBannerEvent( closeSourceToLegacyEventName.get( LegacyCloseSources.SoftCloseAlreadyDonated ), 0.1 );
}
+
+ if ( event.userChoice === CloseChoices.Close ) {
+ return new WMDELegacyBannerEvent( closeSourceToLegacyEventName.get( LegacyCloseSources.SoftCloseXButton ), 0.1 );
+ }
+ }
+
+ if ( event.feature === 'MainBanner' ) {
+ return new WMDELegacyBannerEvent( 'banner-closed-main-without-softclose', 0.1 );
}
if ( event.feature === 'FullPageBanner' ) {
diff --git a/src/tracking/TrackingEvent.ts b/src/tracking/TrackingEvent.ts
index 9403c4e32..9f2327a08 100644
--- a/src/tracking/TrackingEvent.ts
+++ b/src/tracking/TrackingEvent.ts
@@ -12,6 +12,7 @@ export type TrackingFeatureName = '' |
'MainDonationForm' |
'CustomAmountForm' |
'UpgradeToYearlyForm' |
+ 'UpgradeToMonthlyForm' |
'AddressTypeForm';
/**
diff --git a/src/tracking/events/UpgradeToMonthlyEvent.ts b/src/tracking/events/UpgradeToMonthlyEvent.ts
new file mode 100644
index 000000000..9d54baf58
--- /dev/null
+++ b/src/tracking/events/UpgradeToMonthlyEvent.ts
@@ -0,0 +1,14 @@
+import { TrackingEvent, TrackingFeatureName } from '@src/tracking/TrackingEvent';
+
+export class UpgradeToMonthlyEvent implements TrackingEvent {
+ public static readonly EVENT_NAME = 'upgrade-to-monthly';
+
+ public readonly eventName = UpgradeToMonthlyEvent.EVENT_NAME;
+ public readonly customData: Record = {};
+ public readonly feature: TrackingFeatureName = 'UpgradeToYearlyForm';
+ public readonly userChoice: string;
+
+ public constructor( userChoice: 'upgraded-to-monthly'|'not-upgraded-to-monthly' ) {
+ this.userChoice = userChoice;
+ }
+}
From 516300e2b8274d893ffe8c45aecff9097c9edf7d Mon Sep 17 00:00:00 2001
From: Corinna Hillebrand
Date: Thu, 16 Nov 2023 18:47:33 +0100
Subject: [PATCH 3/4] Implement VAR for C23_WMDE_Desktop_DE_13
- adds UpgradeToMonthly Page and tracking for that
- adds new tests for the step controller and form page
https://phabricator.wikimedia.org/T351199
---
banners/desktop/components/BannerVar.vue | 46 ++--
.../components/SoftCloseWithXButton.vue | 9 +-
.../desktop/content/AlreadyDonatedContent.vue | 2 +-
banners/desktop/event_map.ts | 2 +
banners/desktop/messages.ts | 2 +
campaign_info.toml | 6 +-
.../Forms/UpgradeToMonthlyForm.vue | 177 ++++++++++++++
.../Forms/messages/UpgradeToMonthly.de.ts | 15 ++
.../Forms/messages/UpgradeToMonthly.en.ts | 15 ++
...bmittableMainDonationFormUpgradeOptions.ts | 37 +++
.../SubmittableUpgradeToMonthly.ts | 27 +++
src/components/SoftClose/SoftClose.vue | 2 +-
.../LegacyEventTracking/mapCloseEvent.ts | 4 +
.../mapFormStepShownEvent.ts | 1 +
src/tracking/events/UpgradeToMonthlyEvent.ts | 6 +-
.../desktop/components/BannerVar.spec.ts | 11 +-
test/banners/formItems.ts | 3 +-
.../Forms/UpgradeToMonthlyForm.spec.ts | 228 ++++++++++++++++++
.../MainDonation_UpgradeToMonthlyOrYearly.ts | 92 +++++++
.../forms/subForms/UpgradeToMonthlyForm.ts | 30 +++
20 files changed, 672 insertions(+), 43 deletions(-)
create mode 100644 src/components/DonationForm/Forms/UpgradeToMonthlyForm.vue
create mode 100644 src/components/DonationForm/Forms/messages/UpgradeToMonthly.de.ts
create mode 100644 src/components/DonationForm/Forms/messages/UpgradeToMonthly.en.ts
create mode 100644 src/components/DonationForm/StepControllers/SubmittableMainDonationFormUpgradeOptions.ts
create mode 100644 src/components/DonationForm/StepControllers/SubmittableUpgradeToMonthly.ts
create mode 100644 test/components/DonationForm/Forms/UpgradeToMonthlyForm.spec.ts
create mode 100644 test/features/forms/MainDonation_UpgradeToMonthlyOrYearly.ts
create mode 100644 test/features/forms/subForms/UpgradeToMonthlyForm.ts
diff --git a/banners/desktop/components/BannerVar.vue b/banners/desktop/components/BannerVar.vue
index d5a6f88d1..af63c5794 100644
--- a/banners/desktop/components/BannerVar.vue
+++ b/banners/desktop/components/BannerVar.vue
@@ -39,7 +39,17 @@
-
+
@@ -59,7 +69,6 @@
@close="() => onClose( 'SoftClose', CloseChoices.Close )"
@maybeLater="() => onClose( 'SoftClose', CloseChoices.MaybeLater )"
@timeOutClose="() => onClose( 'SoftClose', CloseChoices.TimeOut )"
- @maybeLater7Days="() => onClose('SoftClose', CloseChoices.Close)"
/>
import { BannerStates } from '@src/components/BannerConductor/StateMachine/BannerStates';
-import { computed, ref, watch } from 'vue';
+import { ref, watch } from 'vue';
import { UseOfFundsContent as useOfFundsContentInterface } from '@src/domain/UseOfFunds/UseOfFundsContent';
import SoftClose from './SoftCloseWithXButton.vue';
import MainBanner from './MainBanner.vue';
@@ -98,8 +107,8 @@ import UpgradeToMonthlyForm from '@src/components/DonationForm/Forms/UpgradeToMo
import KeenSlider from '@src/components/Slider/KeenSlider.vue';
import { useFormModel } from '@src/components/composables/useFormModel';
import {
- createSubmittableMainDonationForm
-} from '@src/components/DonationForm/StepControllers/SubmittableMainDonationForm';
+ createSubmittableMainDonationFormUpgradeOptions
+} from '@src/components/DonationForm/StepControllers/SubmittableMainDonationFormUpgradeOptions';
import {
createSubmittableUpgradeToYearly
} from '@src/components/DonationForm/StepControllers/SubmittableUpgradeToYearly';
@@ -139,29 +148,18 @@ const isAlreadyDonatedModalVisible = ref( false );
const contentState = ref( ContentStates.Main );
const formModel = useFormModel();
-const shouldSuggestMonthly = computed( (): boolean => formModel.numericAmount.value >= 11 && formModel.numericAmount.value <= 100 );
-
let stepControllers = [
- createSubmittableMainDonationForm( formModel, FormStepNames.UpgradeToMonthlyFormStep ),
+ createSubmittableMainDonationFormUpgradeOptions(
+ formModel,
+ FormStepNames.UpgradeToYearlyFormStep,
+ FormStepNames.UpgradeToMonthlyFormStep,
+ 11,
+ 100
+ ),
+ createSubmittableUpgradeToYearly( formModel, FormStepNames.MainDonationFormStep, FormStepNames.MainDonationFormStep ),
createSubmittableUpgradeToMonthly( formModel, FormStepNames.MainDonationFormStep, FormStepNames.MainDonationFormStep )
];
-watch( formModel.numericAmount, () => {
- if ( shouldSuggestMonthly.value ) {
- console.log("amount is bigger than 11")
- stepControllers = [
- createSubmittableMainDonationForm( formModel, FormStepNames.UpgradeToMonthlyFormStep ),
- createSubmittableUpgradeToMonthly( formModel, FormStepNames.MainDonationFormStep, FormStepNames.MainDonationFormStep )
- ];
- } else {
- console.log("amount is yearly")
- stepControllers = [
- createSubmittableMainDonationForm( formModel, FormStepNames.UpgradeToYearlyFormStep ),
- createSubmittableUpgradeToYearly( formModel, FormStepNames.MainDonationFormStep, FormStepNames.MainDonationFormStep )
- ];
- }
-} );
-
watch( contentState, async () => {
emit( 'bannerContentChanged' );
} );
diff --git a/banners/desktop/components/SoftCloseWithXButton.vue b/banners/desktop/components/SoftCloseWithXButton.vue
index 68518cd32..313754dd1 100644
--- a/banners/desktop/components/SoftCloseWithXButton.vue
+++ b/banners/desktop/components/SoftCloseWithXButton.vue
@@ -31,7 +31,7 @@
-
+
@@ -52,7 +52,7 @@ const props = withDefaults( defineProps(), {
const timer = ref( 0 );
const secondsRemaining = ref( props.secondsTotal );
-const emit = defineEmits( [ 'close', 'maybeLater', 'timeOutClose', 'maybeLater7Days' ] );
+const emit = defineEmits( [ 'close', 'maybeLater', 'timeOutClose' ] );
const onMaybeLaterClick = (): void => {
window.clearInterval( timer.value );
@@ -64,11 +64,6 @@ const onCloseClick = (): void => {
emit( 'close' );
};
-const onXButtonClick = (): void => {
- window.clearInterval( timer.value );
- emit( 'maybeLater7Days' );
-};
-
onMounted( () => {
timer.value = window.setInterval( () => {
secondsRemaining.value = secondsRemaining.value - 1;
diff --git a/banners/desktop/content/AlreadyDonatedContent.vue b/banners/desktop/content/AlreadyDonatedContent.vue
index 030127d52..eb8eb8f8f 100644
--- a/banners/desktop/content/AlreadyDonatedContent.vue
+++ b/banners/desktop/content/AlreadyDonatedContent.vue
@@ -7,7 +7,7 @@
Falls Sie sich eine (weitere) Spende vorstellen können, dann klicken Sie "Vielleicht später". Falls
- nicht, klicken Sie: "Fürs Erste reicht es". In diesem Fall wird ein Cookie in Ihrem Browser gesetzt,
+ nicht, klicken Sie: "Im Moment nicht". In diesem Fall wird ein Cookie in Ihrem Browser gesetzt,
der die Anzeige der Banner vorerst verhindert.
diff --git a/banners/desktop/event_map.ts b/banners/desktop/event_map.ts
index b4f7e49dd..76469826d 100644
--- a/banners/desktop/event_map.ts
+++ b/banners/desktop/event_map.ts
@@ -25,6 +25,8 @@ export default new Map( [
switch ( e.feature ) {
case 'UpgradeToYearlyForm':
return new WMDESizeIssueEvent( `submit-${e.userChoice}`, createViewportInfo(), 1 );
+ case 'UpgradeToMonthlyForm':
+ return new WMDESizeIssueEvent( `submit-${e.userChoice}`, createViewportInfo(), 1 );
default:
return new WMDESizeIssueEvent( `submit`, createViewportInfo(), 1 );
}
diff --git a/banners/desktop/messages.ts b/banners/desktop/messages.ts
index 2e2c04350..4cde279fe 100644
--- a/banners/desktop/messages.ts
+++ b/banners/desktop/messages.ts
@@ -2,6 +2,7 @@ import CustomAmountFormDe from '@src/components/DonationForm/Forms/messages/Cust
import DynamicCampaignTextDe from '@src/utils/DynamicContent/messages/DynamicCampaignText.de';
import { TranslationMessages } from '@src/Translator';
import UpgradeToYearlyDe from '@src/components/DonationForm/Forms/messages/UpgradeToYearly.de';
+import UpgradeToMonthlyDe from '@src/components/DonationForm/Forms/messages/UpgradeToMonthly.de';
import SoftCloseDe from '@src/components/SoftClose/messages/SoftClose.de';
import AddressFormDe from '@src/components/DonationForm/Forms/messages/AddressForm.de';
import FooterDe from '@src/components/Footer/messages/Footer.de';
@@ -12,6 +13,7 @@ const messages: TranslationMessages = {
...CustomAmountFormDe,
...DynamicCampaignTextDe,
...UpgradeToYearlyDe,
+ ...UpgradeToMonthlyDe,
...SoftCloseDe,
...AddressFormDe,
...FooterDe,
diff --git a/campaign_info.toml b/campaign_info.toml
index c604c35fb..8a577fcd8 100644
--- a/campaign_info.toml
+++ b/campaign_info.toml
@@ -8,7 +8,7 @@ name = "Desktop"
icon = "desktop"
campaign = "C23_WMDE_Desktop_DE_13"
description = "based on ctrl of test 12, variant asks for monthly donations"
-campaign_tracking = "13-ba-231116"
+campaign_tracking = "13-ba-231117"
preview_link = "/wiki/Wikipedia:Hauptseite?devbanner={{banner}}&banner=B22_WMDE_local_prototype"
preview_url = 'https://de.wikipedia.org/wiki/Wikipedia:Hauptseite?banner={{banner}}&devMode'
wrapper_template = "wikipedia_org"
@@ -18,12 +18,12 @@ use_of_funds_source = "MediaWiki:WMDE_Fundraising/UseOfFunds_2023_DE"
[desktop.banners.ctrl]
filename = "./banners/desktop/banner_ctrl.ts"
pagename = "B23_WMDE_Desktop_DE_13_ctrl"
-tracking = "org-13-231116-ctrl"
+tracking = "org-13-231117-ctrl"
[desktop.banners.var]
filename = "./banners/desktop/banner_var.ts"
pagename = "B23_WMDE_Desktop_DE_13_var"
-tracking = "org-13-231116-var"
+tracking = "org-13-231117-var"
[desktop.test_matrix]
platform = ["edge", "firefox_win10", "chrome_win10", "safari", "firefox_macos", "chrome_macos", "firefox_linux", "chrome_linux"]
diff --git a/src/components/DonationForm/Forms/UpgradeToMonthlyForm.vue b/src/components/DonationForm/Forms/UpgradeToMonthlyForm.vue
new file mode 100644
index 000000000..62dad4128
--- /dev/null
+++ b/src/components/DonationForm/Forms/UpgradeToMonthlyForm.vue
@@ -0,0 +1,177 @@
+
+
+
+
+
+
diff --git a/src/components/DonationForm/Forms/messages/UpgradeToMonthly.de.ts b/src/components/DonationForm/Forms/messages/UpgradeToMonthly.de.ts
new file mode 100644
index 000000000..98a9cddc6
--- /dev/null
+++ b/src/components/DonationForm/Forms/messages/UpgradeToMonthly.de.ts
@@ -0,0 +1,15 @@
+import { TranslationMessages } from '@src/Translator';
+
+const Translations: TranslationMessages = {
+ 'upgrade-to-monthly-header': 'Könnten Sie auch {{amount}} monatlich spenden?',
+ 'upgrade-to-monthly-copy': 'Jedes Jahr sind wir auf die Unterstützung von Menschen wie Ihnen angewiesen.' +
+ ' Monatliche Spenden helfen uns nachhaltig und ermöglichen langfristige Weiterentwicklungen.',
+ 'upgrade-to-monthly-no': 'Nein, ich möchte einmalig {{amount}} spenden.',
+ 'upgrade-to-monthly-yes': 'Ja, ich möchte {{amount}} monatlich spenden.',
+ 'upgrade-to-monthly-link': 'Ja, ich möchte monatlich spenden, aber einen anderen Betrag.',
+ 'upgrade-to-monthly-button': 'Weiter, um Spende abzuschließen',
+ 'upgrade-to-monthly-error': 'Bitte wählen Sie eine der Optionen aus.',
+ 'back-button': 'Zurück'
+};
+
+export default Translations;
diff --git a/src/components/DonationForm/Forms/messages/UpgradeToMonthly.en.ts b/src/components/DonationForm/Forms/messages/UpgradeToMonthly.en.ts
new file mode 100644
index 000000000..31871dcf6
--- /dev/null
+++ b/src/components/DonationForm/Forms/messages/UpgradeToMonthly.en.ts
@@ -0,0 +1,15 @@
+import { TranslationMessages } from '@src/Translator';
+
+const Translations: TranslationMessages = {
+ 'upgrade-to-monthly-header': 'Can you make it {{amount}} monthly?',
+ 'upgrade-to-monthly-copy': 'Every year we are dependent on the support of people like you. Monthly donations' +
+ ' help sustainably and enable long term development.',
+ 'upgrade-to-monthly-no': 'No, thanks! I\'ll make a one-time donation of {{amount}}.',
+ 'upgrade-to-monthly-yes': 'Yes, I\'ll donate {{amount}} each year.',
+ 'upgrade-to-monthly-link': 'Yes, I\'ll donate monthly, but for a different amount.',
+ 'upgrade-to-monthly-button': 'Proceed with the donation',
+ 'upgrade-to-monthly-error': 'Please choose one of the above options.',
+ 'back-button': 'Back'
+};
+
+export default Translations;
diff --git a/src/components/DonationForm/StepControllers/SubmittableMainDonationFormUpgradeOptions.ts b/src/components/DonationForm/StepControllers/SubmittableMainDonationFormUpgradeOptions.ts
new file mode 100644
index 000000000..e5492bf49
--- /dev/null
+++ b/src/components/DonationForm/StepControllers/SubmittableMainDonationFormUpgradeOptions.ts
@@ -0,0 +1,37 @@
+import { FormModel } from '@src/utils/FormModel/FormModel';
+import { Intervals } from '@src/utils/FormItemsBuilder/fields/Intervals';
+import { PaymentMethods } from '@src/utils/FormItemsBuilder/fields/PaymentMethods';
+import { StepController } from '@src/components/DonationForm/StepController';
+import { StepAction } from '@src/components/DonationForm/StepNavigation';
+import { BannerSubmitEvent } from '@src/tracking/events/BannerSubmitEvent';
+
+const shouldLeadToMonthlyUpgradePage = ( formModel: FormModel, lowerAmountLimit: number, upperAmountLimit: number ): boolean => {
+ if ( formModel.interval.value !== Intervals.ONCE.value ) {
+ return false;
+ }
+ return formModel.numericAmount.value >= lowerAmountLimit && formModel.numericAmount.value <= upperAmountLimit;
+};
+export function createSubmittableMainDonationFormUpgradeOptions(
+ formModel: FormModel,
+ stepNameOfUpgradeToYearly: string,
+ stepNameOfUpgradeToMonthly: string,
+ lowerAmountLimit: number,
+ upperAmountLimit: number
+): StepController {
+ return {
+ async submit( navigation: StepAction ): Promise {
+ if ( formModel.interval.value !== Intervals.ONCE.value || formModel.paymentMethod.value === PaymentMethods.SOFORT.value ) {
+ await navigation.submit( new BannerSubmitEvent( 'MainDonationForm' ) );
+ return;
+ }
+ if ( shouldLeadToMonthlyUpgradePage( formModel, lowerAmountLimit, upperAmountLimit ) ) {
+ await navigation.goToStep( stepNameOfUpgradeToMonthly );
+ return;
+ }
+ await navigation.goToStep( stepNameOfUpgradeToYearly );
+ },
+ async previous(): Promise {
+ return Promise.reject( 'we can\'t go to previous! This should never happen' );
+ }
+ };
+}
diff --git a/src/components/DonationForm/StepControllers/SubmittableUpgradeToMonthly.ts b/src/components/DonationForm/StepControllers/SubmittableUpgradeToMonthly.ts
new file mode 100644
index 000000000..fe49660d7
--- /dev/null
+++ b/src/components/DonationForm/StepControllers/SubmittableUpgradeToMonthly.ts
@@ -0,0 +1,27 @@
+import { StepController } from '@src/components/DonationForm/StepController';
+import { Intervals } from '@src/utils/FormItemsBuilder/fields/Intervals';
+import { FormModel } from '@src/utils/FormModel/FormModel';
+import { StepAction } from '@src/components/DonationForm/StepNavigation';
+import { BannerSubmitEvent } from '@src/tracking/events/BannerSubmitEvent';
+
+export function createSubmittableUpgradeToMonthly( formModel: FormModel, stepNameOfLinkClick: string, stepNameOfPreviousPage: string ): StepController {
+ return {
+ async submit( navigation: StepAction, submitData: Record ): Promise {
+ formModel.interval.value = submitData.upgradeToMonthlyInterval;
+ if ( submitData.changeOfAmount ) {
+ await navigation.goToStep( stepNameOfLinkClick );
+ return;
+ }
+ formModel.customAmount.value = String( submitData.newNumericAmount );
+ await navigation.submit( new BannerSubmitEvent(
+ 'UpgradeToMonthlyForm',
+ formModel.interval.value === Intervals.MONTHLY.value ? 'recurring' : 'non-recurring'
+ ) );
+ },
+ async previous( navigation: StepAction ): Promise {
+ formModel.interval.value = Intervals.ONCE.value;
+ await navigation.goToStep( stepNameOfPreviousPage );
+
+ }
+ };
+}
diff --git a/src/components/SoftClose/SoftClose.vue b/src/components/SoftClose/SoftClose.vue
index f2e6720d3..50a647182 100644
--- a/src/components/SoftClose/SoftClose.vue
+++ b/src/components/SoftClose/SoftClose.vue
@@ -45,7 +45,7 @@ interface Props {
}
const props = withDefaults( defineProps(), {
- secondsTotal: 35
+ secondsTotal: 15
} );
const timer = ref( 0 );
diff --git a/src/tracking/LegacyEventTracking/mapCloseEvent.ts b/src/tracking/LegacyEventTracking/mapCloseEvent.ts
index 679409730..2bb3a9b7f 100644
--- a/src/tracking/LegacyEventTracking/mapCloseEvent.ts
+++ b/src/tracking/LegacyEventTracking/mapCloseEvent.ts
@@ -20,6 +20,10 @@ export function mapCloseEvent( event: CloseEvent ): WMDELegacyBannerEvent {
return new WMDELegacyBannerEvent( closeSourceToLegacyEventName.get( LegacyCloseSources.AlreadyDonatedGoAway ), 0.1 );
}
+ if ( event.userChoice === CloseChoices.Close ) {
+ return new WMDELegacyBannerEvent( closeSourceToLegacyEventName.get( LegacyCloseSources.AlreadyDonatedMaybeLater ), 0.1 );
+ }
+
if ( event.userChoice === CloseChoices.MaybeLater ) {
return new WMDELegacyBannerEvent( closeSourceToLegacyEventName.get( LegacyCloseSources.AlreadyDonatedMaybeLater ), 0.1 );
}
diff --git a/src/tracking/LegacyEventTracking/mapFormStepShownEvent.ts b/src/tracking/LegacyEventTracking/mapFormStepShownEvent.ts
index ae13ee209..563c97842 100644
--- a/src/tracking/LegacyEventTracking/mapFormStepShownEvent.ts
+++ b/src/tracking/LegacyEventTracking/mapFormStepShownEvent.ts
@@ -7,6 +7,7 @@ import { WMDELegacyBannerEvent } from '@src/tracking/WPORG/WMDELegacyBannerEvent
export function mapFormStepShownEvent( e: FormStepShownEvent ): WMDELegacyBannerEvent {
const stepNameToEventLookup: Record = {
UpgradeToYearlyForm: 'upgrade-to-yearly-form-page-shown',
+ UpgradeToMonthlyForm: 'upgrade-to-monthly-form-page-shown',
CustomAmountForm: 'custom-amount-form-page-shown',
AddressTypeForm: 'address-type-form-page-shown'
};
diff --git a/src/tracking/events/UpgradeToMonthlyEvent.ts b/src/tracking/events/UpgradeToMonthlyEvent.ts
index 9d54baf58..e3082bcd6 100644
--- a/src/tracking/events/UpgradeToMonthlyEvent.ts
+++ b/src/tracking/events/UpgradeToMonthlyEvent.ts
@@ -1,11 +1,11 @@
import { TrackingEvent, TrackingFeatureName } from '@src/tracking/TrackingEvent';
-export class UpgradeToMonthlyEvent implements TrackingEvent {
+export class UpgradeToMonthlyEvent implements TrackingEvent {
public static readonly EVENT_NAME = 'upgrade-to-monthly';
public readonly eventName = UpgradeToMonthlyEvent.EVENT_NAME;
- public readonly customData: Record = {};
- public readonly feature: TrackingFeatureName = 'UpgradeToYearlyForm';
+ public readonly customData: void;
+ public readonly feature: TrackingFeatureName = 'UpgradeToMonthlyForm';
public readonly userChoice: string;
public constructor( userChoice: 'upgraded-to-monthly'|'not-upgraded-to-monthly' ) {
diff --git a/test/banners/desktop/components/BannerVar.spec.ts b/test/banners/desktop/components/BannerVar.spec.ts
index 4804011f3..7332aa970 100644
--- a/test/banners/desktop/components/BannerVar.spec.ts
+++ b/test/banners/desktop/components/BannerVar.spec.ts
@@ -14,7 +14,7 @@ import {
bannerContentDisplaySwitchFeatures,
bannerContentFeatures
} from '@test/features/BannerContent';
-import { donationFormFeatures } from '@test/features/forms/MainDonation_UpgradeToYearlyLink';
+import { donationFormFeatures } from '@test/features/forms/MainDonation_UpgradeToMonthlyOrYearly';
import { useFormModel } from '@src/components/composables/useFormModel';
import { resetFormModel } from '@test/resetFormModel';
import { DynamicContent } from '@src/utils/DynamicContent/DynamicContent';
@@ -95,12 +95,17 @@ describe( 'BannerVar.vue', () => {
test.each( [
[ 'expectMainDonationFormSubmitsWhenSofortIsSelected' ],
[ 'expectMainDonationFormSubmitsWhenYearlyIsSelected' ],
- [ 'expectMainDonationFormGoesToUpgrade' ],
+ [ 'expectMainDonationFormGoesToUpgradeYearlyOnVeryLowAmounts' ],
+ [ 'expectMainDonationFormGoesToUpgradeYearlyOnHighAmounts' ],
+ [ 'expectMainDonationFormGoesToUpgradeMonthly' ],
[ 'expectUpgradeToYearlyFormSubmitsUpgrade' ],
[ 'expectUpgradeToYearlyFormSubmitsDontUpgrade' ],
[ 'expectUpgradeToYearlyFormGoesToMainDonation' ],
[ 'expectUpgradeToYearlyFormSubmitsUpgrade' ],
- [ 'expectUpgradeToYearlyFormSubmitsDontUpgrade' ]
+ [ 'expectUpgradeToYearlyFormSubmitsDontUpgrade' ],
+ [ 'expectUpgradeToMonthlyFormSubmitsUpgrade' ],
+ [ 'expectUpgradeToMonthlyFormSubmitsDontUpgrade' ],
+ [ 'expectUpgradeToMonthlyFormGoesToMainDonation' ]
] )( '%s', async ( testName: string ) => {
await donationFormFeatures[ testName ]( getWrapper() );
} );
diff --git a/test/banners/formItems.ts b/test/banners/formItems.ts
index ed93d45b9..7f665db28 100644
--- a/test/banners/formItems.ts
+++ b/test/banners/formItems.ts
@@ -10,7 +10,8 @@ export const formItems: DonationFormItems = {
{ value: '5', label: '€5', className: 'amount-5' },
{ value: '10', label: '€10', className: 'amount-10' },
{ value: '20', label: '€20', className: 'amount-20' },
- { value: '25', label: '€25', className: 'amount-25' }
+ { value: '25', label: '€25', className: 'amount-25' },
+ { value: '200', label: '€200', className: 'amount-200' }
],
intervals: [ Intervals.ONCE, Intervals.MONTHLY, Intervals.QUARTERLY, Intervals.YEARLY ],
paymentMethods: [ PaymentMethods.PAYPAL, PaymentMethods.CREDIT_CARD, PaymentMethods.SOFORT, PaymentMethods.DIRECT_DEBIT, PaymentMethods.BANK_TRANSFER ]
diff --git a/test/components/DonationForm/Forms/UpgradeToMonthlyForm.spec.ts b/test/components/DonationForm/Forms/UpgradeToMonthlyForm.spec.ts
new file mode 100644
index 000000000..5b74ebbcf
--- /dev/null
+++ b/test/components/DonationForm/Forms/UpgradeToMonthlyForm.spec.ts
@@ -0,0 +1,228 @@
+import { beforeEach, describe, expect, it } from 'vitest';
+import { shallowMount, VueWrapper } from '@vue/test-utils';
+import UpgradeToMonthlyForm from '@src/components/DonationForm/Forms/UpgradeToMonthlyForm.vue';
+import { useFormModel } from '@src/components/composables/useFormModel';
+import { resetFormModel } from '@test/resetFormModel';
+import { CurrencyEn } from '@src/utils/DynamicContent/formatters/CurrencyEn';
+import { TrackerSpy } from '@test/fixtures/TrackerSpy';
+import { UpgradeToMonthlyEvent } from '@src/tracking/events/UpgradeToMonthlyEvent';
+import { FormStepShownEvent } from '@src/tracking/events/FormStepShownEvent';
+import { nextTick } from 'vue';
+
+const formModel = useFormModel();
+
+describe( 'UpgradeToMonthlyForm.vue', () => {
+ let tracker: TrackerSpy;
+
+ // The model values are in the global scope, and they need to be reset before each test
+ beforeEach( () => {
+ resetFormModel( formModel );
+ tracker = new TrackerSpy();
+ } );
+
+ const getWrapper = (): VueWrapper => {
+ return shallowMount( UpgradeToMonthlyForm, {
+ props: {
+ pageIndex: 4,
+ isCurrent: false,
+ suggestions: [
+ {
+ lowerRangeLimit: 11,
+ upperRangeLimit: 100,
+ suggestedAmount: 666
+ }
+ ]
+ },
+ global: {
+ mocks: {
+ $translate: ( key: string, templateTags: Record = {} ) => {
+ return `${key} ${JSON.stringify( templateTags )}`;
+ }
+ },
+ provide: {
+ currencyFormatter: new CurrencyEn(),
+ tracker
+ }
+ }
+ } );
+ };
+
+ it( 'should emit "previous" event when back button is clicked', async () => {
+ const wrapper = getWrapper();
+
+ await wrapper.find( '.wmde-banner-form-upgrade-back' ).trigger( 'click' );
+
+ expect( wrapper.emitted( 'previous' ).length ).toBe( 1 );
+ } );
+
+ it( 'should emit "submit" event with payload when user wants to donate monthly with different amount', async () => {
+ const wrapper = getWrapper();
+ const monthlyIntervalValue = '1';
+
+ await wrapper.find( '.wmde-banner-form-upgrade-custom' ).trigger( 'click' );
+
+ expect( wrapper.emitted( 'submit' ).length ).toBe( 1 );
+ expect( wrapper.emitted( 'submit' )[ 0 ][ 0 ] ).toEqual( { changeOfAmount: true, upgradeToMonthlyInterval: monthlyIntervalValue } );
+ } );
+
+ it( 'should show an error when user does not select any interval ', async function () {
+ const wrapper = getWrapper();
+
+ await wrapper.find( '.wmde-banner-sub-form' ).trigger( 'submit' );
+
+ expect( wrapper.find( '.wmde-banner-select-group-error-message' ).exists() ).toBe( true );
+ expect( wrapper.emitted( 'submit' ) ).toBe( undefined );
+ } );
+
+ it( 'should hide the error when user selects an option', async function () {
+ const wrapper = getWrapper();
+
+ await wrapper.find( '.wmde-banner-sub-form' ).trigger( 'submit' );
+
+ expect( wrapper.find( '.wmde-banner-select-group-error-message' ).exists() ).toBe( true );
+
+ await wrapper.find( '.wmde-banner-select-group-input' ).trigger( 'change' );
+
+ expect( wrapper.find( '.wmde-banner-select-group-error-message' ).exists() ).toBe( false );
+ } );
+
+ it( 'should hide the error when user clicks on the "link" option', async function () {
+ const wrapper = getWrapper();
+
+ await wrapper.find( '.wmde-banner-sub-form' ).trigger( 'submit' );
+
+ expect( wrapper.find( '.wmde-banner-select-group-error-message' ).exists() ).toBe( true );
+
+ await wrapper.find( '.wmde-banner-form-upgrade-custom' ).trigger( 'click' );
+
+ expect( wrapper.find( '.wmde-banner-select-group-error-message' ).exists() ).toBe( false );
+ } );
+
+ it( 'should emit "submit" event when user selects an interval and submits ', async function () {
+ const wrapper = getWrapper();
+
+ await wrapper.find( '.wmde-banner-select-group-input' ).trigger( 'change' );
+ await wrapper.find( '.wmde-banner-sub-form' ).trigger( 'submit' );
+
+ expect( wrapper.find( '.wmde-banner-select-group-error-message' ).exists() ).toBe( false );
+ expect( wrapper.emitted( 'submit' ).length ).toBe( 1 );
+ } );
+
+ it( 'should submit the chosen interval and new numeric amount when form was submitted ', async function () {
+ const wrapper = getWrapper();
+ formModel.selectedAmount.value = '22';
+ const monthlyIntervalValue = '1';
+
+ await wrapper.find( '.wmde-banner-select-group-option-no .wmde-banner-select-group-input' ).trigger( 'change' );
+ await wrapper.find( '.wmde-banner-sub-form' ).trigger( 'submit' );
+
+ await wrapper.find( '.wmde-banner-select-group-option-yes .wmde-banner-select-group-input' ).trigger( 'change' );
+ await wrapper.find( '.wmde-banner-sub-form' ).trigger( 'submit' );
+
+ expect( wrapper.emitted( 'submit' ).length ).toBe( 2 );
+ expect( wrapper.emitted( 'submit' )[ 0 ][ 0 ] ).toEqual( {
+ changeOfAmount: false,
+ newNumericAmount: Number( '22' ),
+ upgradeToMonthlyInterval: '0'
+ } );
+ expect( wrapper.emitted( 'submit' )[ 1 ][ 0 ] ).toEqual( {
+ changeOfAmount: false,
+ newNumericAmount: Number( '666' ),
+ upgradeToMonthlyInterval: monthlyIntervalValue
+ } );
+ } );
+
+ it( 'should insert the euroAmount into the translations', async () => {
+ const wrapper = getWrapper();
+
+ // this simulates the user selecting an amount on the first page, triggering the watcher for the visible amounts
+ formModel.selectedAmount.value = '20';
+ await nextTick();
+
+ expect( wrapper.find( '.wmde-banner-form-upgrade-notice strong' ).text() ).toContain( '{"amount":"€666"}' );
+ expect( wrapper.find( '.wmde-banner-select-group-option-no .wmde-banner-select-group-label' ).text() ).toContain( '{"amount":"€20"}' );
+ expect( wrapper.find( '.wmde-banner-select-group-option-yes .wmde-banner-select-group-label' ).text() ).toContain( '{"amount":"€666"}' );
+ } );
+
+ it( 'should not change visible amounts when monthly form is the current form', async () => {
+ const wrapper = getWrapper();
+
+ // this simulates the user selecting an amount on the first page, triggering the watcher for the visible amounts
+ formModel.selectedAmount.value = '20';
+ await nextTick();
+
+ wrapper.setProps( { isCurrent: true } );
+
+ // this simulates the submit event handler setting the new amount (in the store)
+ formModel.selectedAmount.value = '30';
+ await nextTick();
+
+ expect( wrapper.find( '.wmde-banner-form-upgrade-notice strong' ).text() ).toContain( '{"amount":"€666"}' );
+ expect( wrapper.find( '.wmde-banner-select-group-option-no .wmde-banner-select-group-label' ).text() ).toContain( '{"amount":"€20"}' );
+ expect( wrapper.find( '.wmde-banner-select-group-option-yes .wmde-banner-select-group-label' ).text() ).toContain( '{"amount":"€666"}' );
+ } );
+
+ it( 'should reset the error message when going to the previous page', async () => {
+ const wrapper = getWrapper();
+
+ await wrapper.find( '.wmde-banner-sub-form' ).trigger( 'submit' );
+
+ expect( wrapper.find( '.wmde-banner-select-group-error-message' ).exists() ).toBe( true );
+
+ await wrapper.find( '.wmde-banner-form-upgrade-back' ).trigger( 'click' );
+
+ expect( wrapper.find( '.wmde-banner-select-group-error-message' ).exists() ).toBe( false );
+ } );
+
+ it( 'should reset the value when going to the previous page', async () => {
+ const wrapper = getWrapper();
+
+ await wrapper.find( '.wmde-banner-select-group-option-no .wmde-banner-select-group-input' ).trigger( 'change' );
+ await wrapper.find( '.wmde-banner-form-upgrade-back' ).trigger( 'click' );
+
+ const options = wrapper.findAll( '.wmde-banner-select-group-input' );
+ expect( options[ 0 ].element.checked ).toBe( false );
+ expect( options[ 1 ].element.checked ).toBe( false );
+ } );
+
+ it( 'should emit back event', async () => {
+ const wrapper = getWrapper();
+
+ await wrapper.find( '.wmde-banner-form-upgrade-back' ).trigger( 'click' );
+
+ expect( wrapper.emitted( 'previous' ).length ).toBe( 1 );
+ } );
+
+ describe( 'tracking events ', function () {
+
+ it( 'should track "Upgrade to monthly" event when user chooses Upgrade to monthly', async function () {
+ const wrapper = getWrapper();
+
+ await wrapper.find( '.wmde-banner-select-group-option-yes .wmde-banner-select-group-input' ).trigger( 'change' );
+ await wrapper.find( '.wmde-banner-sub-form' ).trigger( 'submit' );
+
+ expect( tracker.hasTrackedEvent( UpgradeToMonthlyEvent.EVENT_NAME ) ).toBe( true );
+ expect( tracker.getTrackedEvent( UpgradeToMonthlyEvent.EVENT_NAME ) ).toEqual( new UpgradeToMonthlyEvent( 'upgraded-to-monthly' ) );
+
+ } );
+
+ it( 'should track "Not upgraded to monthly" event when user does not choose Upgrade to monthly', async function () {
+ const wrapper = getWrapper();
+
+ await wrapper.find( '.wmde-banner-select-group-option-no .wmde-banner-select-group-input' ).trigger( 'change' );
+ await wrapper.find( '.wmde-banner-sub-form' ).trigger( 'submit' );
+
+ expect( tracker.hasTrackedEvent( UpgradeToMonthlyEvent.EVENT_NAME ) ).toBe( true );
+ expect( tracker.getTrackedEvent( UpgradeToMonthlyEvent.EVENT_NAME ) ).toEqual( new UpgradeToMonthlyEvent( 'not-upgraded-to-monthly' ) );
+ } );
+
+ it( 'sends the FormStepShownEvent to tracker when the form becomes the current form', async () => {
+ const wrapper = getWrapper();
+
+ await wrapper.setProps( { isCurrent: true } );
+
+ expect( tracker.hasTrackedEvent( FormStepShownEvent.EVENT_NAME ) ).toBe( true );
+ expect( tracker.getTrackedEvent( FormStepShownEvent.EVENT_NAME ) ).toEqual( new FormStepShownEvent( 'UpgradeToMonthlyForm' ) );
+ } );
+ } );
+} );
diff --git a/test/features/forms/MainDonation_UpgradeToMonthlyOrYearly.ts b/test/features/forms/MainDonation_UpgradeToMonthlyOrYearly.ts
new file mode 100644
index 000000000..755d91d29
--- /dev/null
+++ b/test/features/forms/MainDonation_UpgradeToMonthlyOrYearly.ts
@@ -0,0 +1,92 @@
+import { VueWrapper } from '@vue/test-utils';
+import {
+ expectMainDonationFormGoesToPageOnSubmit,
+ expectMainDonationFormSubmits,
+ submitMainDonationForm
+} from '@test/features/forms/subForms/MainDonationForm';
+import {
+ expectUpgradeToYearlyFormGoesToPageOnLinkClick,
+ expectUpgradeToYearlyFormSubmits
+} from '@test/features/forms/subForms/UpgradeToYearlyForm';
+import {
+ expectUpgradeToMonthlyFormGoesToPageOnLinkClick,
+ expectUpgradeToMonthlyFormSubmits
+} from '@test/features/forms/subForms/UpgradeToMonthlyForm';
+import { Intervals } from '@src/utils/FormItemsBuilder/fields/Intervals';
+import { PaymentMethods } from '@src/utils/FormItemsBuilder/fields/PaymentMethods';
+
+enum Pages {
+ MainDonation = 1,
+ UpgradeToYearly = 2,
+ UpgradeToMonthly = 3
+}
+
+export const donationFormFeatures: Record ) => Promise> = {
+ expectMainDonationFormSubmitsWhenSofortIsSelected: ( wrapper: VueWrapper ) => expectMainDonationFormSubmits(
+ wrapper,
+ Intervals.ONCE,
+ PaymentMethods.SOFORT,
+ '5'
+ ),
+ expectMainDonationFormSubmitsWhenYearlyIsSelected: ( wrapper: VueWrapper ) => expectMainDonationFormSubmits(
+ wrapper,
+ Intervals.YEARLY,
+ PaymentMethods.PAYPAL,
+ '5'
+ ),
+ expectMainDonationFormSubmitsWhenMonthlyIsSelected: ( wrapper: VueWrapper ) => expectMainDonationFormSubmits(
+ wrapper,
+ Intervals.MONTHLY,
+ PaymentMethods.PAYPAL,
+ '5'
+ ),
+ expectMainDonationFormSubmitsWhenAmountIsGreaterThanMaxAmount: async ( wrapper: VueWrapper ) => expectMainDonationFormSubmits(
+ wrapper,
+ Intervals.YEARLY,
+ PaymentMethods.PAYPAL,
+ '25'
+ ),
+ expectMainDonationFormGoesToUpgradeYearlyOnHighAmounts: ( wrapper: VueWrapper ) => expectMainDonationFormGoesToPageOnSubmit( wrapper,
+ Pages.UpgradeToYearly,
+ Intervals.ONCE,
+ PaymentMethods.PAYPAL,
+ '200'
+ ),
+ expectMainDonationFormGoesToUpgradeYearlyOnVeryLowAmounts: ( wrapper: VueWrapper ) => expectMainDonationFormGoesToPageOnSubmit( wrapper,
+ Pages.UpgradeToYearly,
+ Intervals.ONCE,
+ PaymentMethods.PAYPAL,
+ '1'
+ ),
+ expectMainDonationFormGoesToUpgradeMonthly: ( wrapper: VueWrapper ) => expectMainDonationFormGoesToPageOnSubmit( wrapper,
+ Pages.UpgradeToMonthly,
+ Intervals.ONCE,
+ PaymentMethods.PAYPAL,
+ '20'
+ ),
+ expectUpgradeToYearlyFormSubmitsUpgrade: async ( wrapper: VueWrapper ) => {
+ await submitMainDonationForm( wrapper, Intervals.ONCE, '5', PaymentMethods.PAYPAL );
+ await expectUpgradeToYearlyFormSubmits( wrapper, 'yes' );
+ },
+ expectUpgradeToYearlyFormSubmitsDontUpgrade: async ( wrapper: VueWrapper ) => {
+ await submitMainDonationForm( wrapper, Intervals.ONCE, '5', PaymentMethods.PAYPAL );
+ await expectUpgradeToYearlyFormSubmits( wrapper, 'no' );
+ },
+ expectUpgradeToYearlyFormGoesToMainDonation: async ( wrapper: VueWrapper ) => {
+ await submitMainDonationForm( wrapper, Intervals.ONCE, '5', PaymentMethods.PAYPAL );
+ await expectUpgradeToYearlyFormGoesToPageOnLinkClick( wrapper, Pages.MainDonation );
+ },
+
+ expectUpgradeToMonthlyFormSubmitsUpgrade: async ( wrapper: VueWrapper ) => {
+ await submitMainDonationForm( wrapper, Intervals.ONCE, '5', PaymentMethods.PAYPAL );
+ await expectUpgradeToMonthlyFormSubmits( wrapper, 'yes' );
+ },
+ expectUpgradeToMonthlyFormSubmitsDontUpgrade: async ( wrapper: VueWrapper ) => {
+ await submitMainDonationForm( wrapper, Intervals.ONCE, '5', PaymentMethods.PAYPAL );
+ await expectUpgradeToMonthlyFormSubmits( wrapper, 'no' );
+ },
+ expectUpgradeToMonthlyFormGoesToMainDonation: async ( wrapper: VueWrapper ) => {
+ await submitMainDonationForm( wrapper, Intervals.ONCE, '5', PaymentMethods.PAYPAL );
+ await expectUpgradeToMonthlyFormGoesToPageOnLinkClick( wrapper, Pages.MainDonation );
+ }
+};
diff --git a/test/features/forms/subForms/UpgradeToMonthlyForm.ts b/test/features/forms/subForms/UpgradeToMonthlyForm.ts
new file mode 100644
index 000000000..9b133a9d4
--- /dev/null
+++ b/test/features/forms/subForms/UpgradeToMonthlyForm.ts
@@ -0,0 +1,30 @@
+import { VueWrapper } from '@vue/test-utils';
+import { expect, vi } from 'vitest';
+
+export const submitUpgradeToMonthlyForm = async ( wrapper: VueWrapper, upgrade: 'yes' | 'no' ): Promise => {
+ await wrapper.find( `.wmde-banner-select-group-option-${upgrade} .wmde-banner-select-group-input` ).setValue();
+ await wrapper.find( '.wmde-banner-form-upgrade' ).trigger( 'submit' );
+};
+
+export const expectUpgradeToMonthlyFormSubmits = async ( wrapper: VueWrapper, upgrade: 'yes' | 'no' ): Promise => {
+ const submitForm = wrapper.find( '.wmde-banner-submit-form' );
+ submitForm.element.submit = vi.fn();
+
+ await submitUpgradeToMonthlyForm( wrapper, upgrade );
+
+ expect( submitForm.element.submit ).toHaveBeenCalledOnce();
+};
+
+export const expectUpgradeToMonthlyFormGoesToPageOnSubmit = async ( wrapper: VueWrapper, page: number, upgrade: 'yes' | 'no' ): Promise => {
+ await submitUpgradeToMonthlyForm( wrapper, upgrade );
+
+ expect( wrapper.find( `.wmde-banner-form-page:nth-child(${page})` ).attributes( 'class' ) )
+ .toContain( 'wmde-banner-form-page--current' );
+};
+
+export const expectUpgradeToMonthlyFormGoesToPageOnLinkClick = async ( wrapper: VueWrapper, page: number ): Promise => {
+ await wrapper.find( '.wmde-banner-form-upgrade-custom' ).trigger( 'click' );
+
+ expect( wrapper.find( `.wmde-banner-form-page:nth-child(${page})` ).attributes( 'class' ) )
+ .toContain( 'wmde-banner-form-page--current' );
+};
From cce2bc031272d086ead2c7eaac77e0f4c974db97 Mon Sep 17 00:00:00 2001
From: Abban Dunne
Date: Tue, 21 Nov 2023 16:51:48 +0100
Subject: [PATCH 4/4] Add step controller tests (#287)
Ticket: https://phabricator.wikimedia.org/T351199
---
...ableMainDonationFormUpgradeOptions.spec.ts | 117 ++++++++++++++++++
...ableMainDonationFormWhenOverAmount.spec.ts | 4 +-
.../SubmittableUpgradeToMonthly.spec.ts | 78 ++++++++++++
3 files changed, 197 insertions(+), 2 deletions(-)
create mode 100644 test/components/DonationForm/StepControllers/SubmittableMainDonationFormUpgradeOptions.spec.ts
create mode 100644 test/components/DonationForm/StepControllers/SubmittableUpgradeToMonthly.spec.ts
diff --git a/test/components/DonationForm/StepControllers/SubmittableMainDonationFormUpgradeOptions.spec.ts b/test/components/DonationForm/StepControllers/SubmittableMainDonationFormUpgradeOptions.spec.ts
new file mode 100644
index 000000000..fc5829bd6
--- /dev/null
+++ b/test/components/DonationForm/StepControllers/SubmittableMainDonationFormUpgradeOptions.spec.ts
@@ -0,0 +1,117 @@
+import { beforeEach, describe, expect, it, test, vi } from 'vitest';
+import { StepAction } from '@src/components/DonationForm/StepNavigation';
+import { resetFormModel } from '@test/resetFormModel';
+import { PaymentMethods } from '@src/utils/FormItemsBuilder/fields/PaymentMethods';
+import { Intervals } from '@src/utils/FormItemsBuilder/fields/Intervals';
+import {
+ createSubmittableMainDonationFormUpgradeOptions
+} from '@src/components/DonationForm/StepControllers/SubmittableMainDonationFormUpgradeOptions';
+import { useFormModel } from '@src/components/composables/useFormModel';
+
+const formModel = useFormModel();
+
+describe( 'SubmittableMainDonationFormUpgradeOptions', () => {
+ let stepNavigation: StepAction;
+
+ // The model values are in the global scope, and they need to be reset before each test
+ beforeEach( () => {
+ resetFormModel( formModel );
+ stepNavigation = {
+ goToStep: vi.fn(),
+ submit: vi.fn()
+ };
+ } );
+
+ test.each( [
+ [ PaymentMethods.PAYPAL.value, '10', 'yearly' ],
+ [ PaymentMethods.BANK_TRANSFER.value, '10', 'yearly' ],
+ [ PaymentMethods.CREDIT_CARD.value, '10', 'yearly' ],
+ [ PaymentMethods.DIRECT_DEBIT.value, '10', 'yearly' ],
+ [ PaymentMethods.PAYPAL.value, '101', 'yearly' ],
+ [ PaymentMethods.BANK_TRANSFER.value, '101', 'yearly' ],
+ [ PaymentMethods.CREDIT_CARD.value, '101', 'yearly' ],
+ [ PaymentMethods.DIRECT_DEBIT.value, '101', 'yearly' ],
+ [ PaymentMethods.PAYPAL.value, '12', 'monthly' ],
+ [ PaymentMethods.BANK_TRANSFER.value, '12', 'monthly' ],
+ [ PaymentMethods.CREDIT_CARD.value, '12', 'monthly' ],
+ [ PaymentMethods.DIRECT_DEBIT.value, '12', 'monthly' ]
+ ] )( 'goes to correct step when payment method is not Sofort and amount is in upgrade range', async ( paymentMethod: string, selectedAmount: string, expectedPage: string ) => {
+ formModel.paymentMethod.value = paymentMethod;
+ formModel.interval.value = Intervals.ONCE.value;
+ formModel.selectedAmount.value = selectedAmount;
+ const donationForm = createSubmittableMainDonationFormUpgradeOptions(
+ formModel,
+ 'yearly',
+ 'monthly',
+ 11,
+ 100
+ );
+
+ await donationForm.submit( stepNavigation, {} );
+
+ expect( stepNavigation.goToStep ).toHaveBeenCalledOnce();
+ expect( stepNavigation.goToStep ).toHaveBeenCalledWith( expectedPage );
+ } );
+
+ test.each( [
+ [ PaymentMethods.SOFORT.value, '10' ],
+ [ PaymentMethods.SOFORT.value, '12' ],
+ [ PaymentMethods.SOFORT.value, '101' ]
+ ] )( 'submits when payment method is sofort', async ( paymentMethod: string, selectedAmount: string ) => {
+ formModel.interval.value = Intervals.ONCE.value;
+ formModel.paymentMethod.value = paymentMethod;
+ formModel.selectedAmount.value = selectedAmount;
+ const donationForm = createSubmittableMainDonationFormUpgradeOptions(
+ formModel,
+ 'yearly',
+ 'monthly',
+ 11,
+ 100
+ );
+
+ await donationForm.submit( stepNavigation, {} );
+
+ expect( stepNavigation.submit ).toHaveBeenCalledOnce();
+ } );
+
+ test.each( [
+ [ Intervals.MONTHLY.value, '10' ],
+ [ Intervals.QUARTERLY.value, '10' ],
+ [ Intervals.BIANNUAL.value, '10' ],
+ [ Intervals.YEARLY.value, '10' ],
+ [ Intervals.MONTHLY.value, '11' ],
+ [ Intervals.QUARTERLY.value, '11' ],
+ [ Intervals.BIANNUAL.value, '11' ],
+ [ Intervals.YEARLY.value, '11' ],
+ [ Intervals.MONTHLY.value, '101' ],
+ [ Intervals.QUARTERLY.value, '101' ],
+ [ Intervals.BIANNUAL.value, '101' ],
+ [ Intervals.YEARLY.value, '101' ]
+ ] )( 'submits when interval is not once', async ( interval: string ) => {
+ formModel.interval.value = interval;
+ formModel.paymentMethod.value = PaymentMethods.PAYPAL.value;
+ const donationForm = createSubmittableMainDonationFormUpgradeOptions(
+ formModel,
+ 'yearly',
+ 'monthly',
+ 11,
+ 100
+ );
+
+ await donationForm.submit( stepNavigation, {} );
+
+ expect( stepNavigation.submit ).toHaveBeenCalledOnce();
+ } );
+
+ it( 'rejects calls to previous', async () => {
+ const donationForm = createSubmittableMainDonationFormUpgradeOptions(
+ formModel,
+ 'yearly',
+ 'monthly',
+ 11,
+ 100
+ );
+
+ expect( donationForm.previous( stepNavigation ) ).rejects.toEqual( 'we can\'t go to previous! This should never happen' );
+ } );
+} );
diff --git a/test/components/DonationForm/StepControllers/SubmittableMainDonationFormWhenOverAmount.spec.ts b/test/components/DonationForm/StepControllers/SubmittableMainDonationFormWhenOverAmount.spec.ts
index 87e949926..24c70696d 100644
--- a/test/components/DonationForm/StepControllers/SubmittableMainDonationFormWhenOverAmount.spec.ts
+++ b/test/components/DonationForm/StepControllers/SubmittableMainDonationFormWhenOverAmount.spec.ts
@@ -27,7 +27,7 @@ describe( 'SubmittableMainDonationFormWhenOverAmount', () => {
[ PaymentMethods.BANK_TRANSFER.value ],
[ PaymentMethods.CREDIT_CARD.value ],
[ PaymentMethods.DIRECT_DEBIT.value ]
- ] )( 'submits when payment method is Sofort', async ( paymentMethod: string ) => {
+ ] )( 'goes to upgrade when payment method is not Sofort', async ( paymentMethod: string ) => {
formModel.paymentMethod.value = paymentMethod;
formModel.interval.value = Intervals.ONCE.value;
const donationForm = createSubmittableMainDonationFormWhenOverAmount( formModel, 'yearly', 100 );
@@ -38,7 +38,7 @@ describe( 'SubmittableMainDonationFormWhenOverAmount', () => {
expect( stepNavigation.goToStep ).toHaveBeenCalledWith( 'yearly' );
} );
- it( 'goes to upgrade when payment method is not Sofort', async () => {
+ it( 'submits when payment method is Sofort', async () => {
formModel.paymentMethod.value = PaymentMethods.SOFORT.value;
formModel.interval.value = Intervals.ONCE.value;
const donationForm = createSubmittableMainDonationFormWhenOverAmount( formModel, 'yearly', 100 );
diff --git a/test/components/DonationForm/StepControllers/SubmittableUpgradeToMonthly.spec.ts b/test/components/DonationForm/StepControllers/SubmittableUpgradeToMonthly.spec.ts
new file mode 100644
index 000000000..04362ef94
--- /dev/null
+++ b/test/components/DonationForm/StepControllers/SubmittableUpgradeToMonthly.spec.ts
@@ -0,0 +1,78 @@
+import { beforeEach, describe, expect, it, vi } from 'vitest';
+import { useFormModel } from '@src/components/composables/useFormModel';
+import { StepAction } from '@src/components/DonationForm/StepNavigation';
+import { resetFormModel } from '@test/resetFormModel';
+import { Intervals } from '@src/utils/FormItemsBuilder/fields/Intervals';
+import { BannerSubmitEvent } from '@src/tracking/events/BannerSubmitEvent';
+import {
+ createSubmittableUpgradeToMonthly
+} from '@src/components/DonationForm/StepControllers/SubmittableUpgradeToMonthly';
+
+const formModel = useFormModel();
+
+describe( 'SubmittableUpgradeToMonthly', () => {
+ let stepNavigation: StepAction;
+
+ // The model values are in the global scope, and they need to be reset before each test
+ beforeEach( () => {
+ resetFormModel( formModel );
+ stepNavigation = {
+ goToStep: vi.fn(),
+ submit: vi.fn()
+ };
+ } );
+
+ it( 'submits when user selects option', async () => {
+ const upgrade = createSubmittableUpgradeToMonthly( formModel, 'link', 'previous' );
+
+ await upgrade.submit( stepNavigation, {} );
+
+ expect( stepNavigation.submit ).toHaveBeenCalledOnce();
+ } );
+
+ it( 'goes to link step when user clicks link', async () => {
+ const upgrade = createSubmittableUpgradeToMonthly( formModel, 'link', 'previous' );
+
+ await upgrade.submit( stepNavigation, { changeOfAmount: 'true' } );
+
+ expect( stepNavigation.goToStep ).toHaveBeenCalledOnce();
+ expect( stepNavigation.goToStep ).toHaveBeenCalledWith( 'link' );
+ } );
+
+ it( 'sets form interval to once on previous', async () => {
+ formModel.interval.value = Intervals.YEARLY.value;
+ const upgrade = createSubmittableUpgradeToMonthly( formModel, 'link', 'previous' );
+
+ await upgrade.previous( stepNavigation );
+
+ expect( formModel.interval.value ).toBe( Intervals.ONCE.value );
+ } );
+
+ it( 'goes to previous step on previous', async () => {
+ formModel.interval.value = Intervals.YEARLY.value;
+ const upgrade = createSubmittableUpgradeToMonthly( formModel, 'link', 'previous' );
+
+ await upgrade.previous( stepNavigation );
+
+ expect( stepNavigation.goToStep ).toHaveBeenCalledOnce();
+ expect( stepNavigation.goToStep ).toHaveBeenCalledWith( 'previous' );
+ } );
+
+ describe( 'tracking events', function () {
+ it( 'converts recurring interval to "submit" event with the correct option selected', async () => {
+ const upgrade = createSubmittableUpgradeToMonthly( formModel, 'link', 'previous' );
+
+ await upgrade.submit( stepNavigation, { upgradeToMonthlyInterval: Intervals.MONTHLY.value } );
+
+ expect( stepNavigation.submit ).toHaveBeenCalledWith( new BannerSubmitEvent( 'UpgradeToMonthlyForm', 'recurring' ) );
+ } );
+
+ it( 'converts non-recurring interval to "submit" event with the correct option selected', async () => {
+ const upgrade = createSubmittableUpgradeToMonthly( formModel, 'link', 'previous' );
+
+ await upgrade.submit( stepNavigation, { upgradeToMonthlyInterval: Intervals.ONCE.value } );
+
+ expect( stepNavigation.submit ).toHaveBeenCalledWith( new BannerSubmitEvent( 'UpgradeToMonthlyForm', 'non-recurring' ) );
+ } );
+ } );
+} );