Remove payments API routing initialization
[ProtonMail-WebClient.git] / packages / components / containers / payments / RenewalNotice.test.tsx
blob7147d4dc0d2fea4762bc3d54d63ea4f486e4db01
1 import { render } from '@testing-library/react';
2 import { addMonths } from 'date-fns';
4 import { ADDON_NAMES, PLANS, PLAN_TYPES, type PlanIDs } from '@proton/payments';
5 import { CYCLE } from '@proton/shared/lib/constants';
6 import { type RequiredCheckResponse, getCheckout } from '@proton/shared/lib/helpers/checkout';
7 import { toMap } from '@proton/shared/lib/helpers/object';
8 import type { PlansMap, Subscription } from '@proton/shared/lib/interfaces';
9 import { getFreeCheckResult } from '@proton/shared/lib/subscription/freePlans';
11 import { getCheckoutRenewNoticeText } from './RenewalNotice';
13 const RenewalNotice = (...props: Parameters<typeof getCheckoutRenewNoticeText>) => {
14     return <div>{getCheckoutRenewNoticeText(...props)}</div>;
17 const getDefaultPlansMap = (): PlansMap => {
18     const plans = [
19         {
20             ID: 'KV8mjImpquR4tux9teokTx9bRB3GDgJYgDV2r1PCaCVD9o8InZs99CZr_q2G0qyP8QES4FZyxdO5gU1K-2Jv7Q==',
21             ParentMetaPlanID:
22                 'hUcV0_EeNwUmXA6EoyNrtO-ZTD8H8F6LvNaSjMaPxB5ecFkA7y-5kc3q38cGumJENGHjtSoUndkYFUx0_xlJeg==',
23             Type: 1,
24             Name: 'vpn2024',
25             Title: 'VPN Plus',
26             MaxDomains: 0,
27             MaxAddresses: 0,
28             MaxCalendars: 0,
29             MaxSpace: 0,
30             MaxMembers: 0,
31             MaxVPN: 10,
32             MaxTier: 2,
33             Services: 4,
34             Features: 0,
35             State: 1,
36             Pricing: {
37                 '1': 999,
38                 '3': 2397,
39                 '12': 7995,
40                 '15': 14985,
41                 '18': 8982,
42                 '24': 11976,
43                 '30': 29970,
44             },
45             DefaultPricing: {
46                 '1': 999,
47                 '3': 2397,
48                 '12': 7995,
49                 '15': 14985,
50                 '18': 8982,
51                 '24': 11976,
52                 '30': 29970,
53             },
54             PeriodEnd: {
55                 '1': 1719497218,
56                 '3': 1724767618,
57                 '12': 1748354818,
58                 '15': 1756303618,
59                 '18': 1764252418,
60                 '24': 1779890818,
61                 '30': 1795788418,
62             },
63             Currency: 'CHF',
64             Quantity: 1,
65             Offers: [],
66             Cycle: 12,
67             Amount: 7995,
68             Vendors: {
69                 Google: {
70                     Plans: {},
71                     CustomerID: 'cus_google_gOjTbjOE83fpVtO8A7ZY',
72                 },
73                 Apple: {
74                     Plans: {},
75                     CustomerID: '',
76                 },
77             },
78         },
79         {
80             ID: 'vXOiCO533JxXlqJsrhvREDwaFhGOXXV7NYjsz06VDJGSnes72blaG8hA9547xU1NLrMsDbA3lywhjPZ7oNYNcA==',
81             ParentMetaPlanID:
82                 'hUcV0_EeNwUmXA6EoyNrtO-ZTD8H8F6LvNaSjMaPxB5ecFkA7y-5kc3q38cGumJENGHjtSoUndkYFUx0_xlJeg==',
83             Type: 1,
84             Name: 'mail2022',
85             Title: 'Mail Plus',
86             MaxDomains: 1,
87             MaxAddresses: 10,
88             MaxCalendars: 25,
89             MaxSpace: 16106127360,
90             MaxMembers: 1,
91             MaxVPN: 0,
92             MaxTier: 0,
93             Services: 1,
94             Features: 1,
95             State: 1,
96             Pricing: {
97                 '1': 499,
98                 '12': 4788,
99                 '24': 8376,
100             },
101             DefaultPricing: {
102                 '1': 499,
103                 '12': 4788,
104                 '24': 8376,
105             },
106             PeriodEnd: {
107                 '1': 1719497218,
108                 '12': 1748354818,
109                 '24': 1779890818,
110             },
111             Currency: 'CHF',
112             Quantity: 1,
113             Offers: [],
114             Cycle: 1,
115             Amount: 499,
116             Vendors: {
117                 Google: {
118                     Plans: {},
119                     CustomerID: 'cus_google_gOjTbjOE83fpVtO8A7ZY',
120                 },
121                 Apple: {
122                     Plans: {},
123                     CustomerID: '',
124                 },
125             },
126         },
127         {
128             ID: 'yu50U8Rf9dhPHDcG3KTX6Nx3Euupk4uskAj9V9YVCFSB3oQk8_pTGfWwRFkRPYziGL5EsEx42ZyRHdcZxpO8CA==',
129             ParentMetaPlanID:
130                 'hUcV0_EeNwUmXA6EoyNrtO-ZTD8H8F6LvNaSjMaPxB5ecFkA7y-5kc3q38cGumJENGHjtSoUndkYFUx0_xlJeg==',
131             Type: 1,
132             Name: 'vpnpass2023',
133             Title: 'VPN and Pass bundle',
134             MaxDomains: 0,
135             MaxAddresses: 0,
136             MaxCalendars: 0,
137             MaxSpace: 0,
138             MaxMembers: 0,
139             MaxVPN: 10,
140             MaxTier: 2,
141             Services: 12,
142             Features: 0,
143             State: 1,
144             Pricing: {
145                 '1': 1099,
146                 '12': 9588,
147                 '15': 11985,
148                 '24': 14376,
149                 '30': 17970,
150             },
151             DefaultPricing: {
152                 '1': 1099,
153                 '12': 9588,
154                 '15': 11985,
155                 '24': 14376,
156                 '30': 17970,
157             },
158             PeriodEnd: {
159                 '1': 1719497218,
160                 '12': 1748354818,
161                 '15': 1756303618,
162                 '24': 1779890818,
163                 '30': 1795788418,
164             },
165             Currency: 'CHF',
166             Quantity: 1,
167             Offers: [],
168             Cycle: 12,
169             Amount: 9588,
170             Vendors: {
171                 Google: {
172                     Plans: {},
173                     CustomerID: 'cus_google_gOjTbjOE83fpVtO8A7ZY',
174                 },
175                 Apple: {
176                     Plans: {},
177                     CustomerID: '',
178                 },
179             },
180         },
181     ];
182     return toMap(plans, 'Name');
185 const defaultPlansMap = getDefaultPlansMap();
187 const getProps = (
188     {
189         plansMap = defaultPlansMap,
190         planIDs = { [PLANS.MAIL]: 1 },
191         checkResult,
192     }: {
193         planIDs?: PlanIDs;
194         plansMap?: PlansMap;
195         checkResult: RequiredCheckResponse;
196     } = {
197         checkResult: getFreeCheckResult(),
198     }
199 ): Pick<
200     Parameters<typeof getCheckoutRenewNoticeText>[0],
201     'planIDs' | 'checkout' | 'plansMap' | 'coupon' | 'currency'
202 > => {
203     const checkout = getCheckout({ planIDs, plansMap, checkResult });
204     return {
205         planIDs,
206         checkout,
207         plansMap,
208         coupon: checkResult?.Coupon || null,
209         currency: 'CHF' as const,
210     };
213 describe('<RenewalNotice />', () => {
214     beforeEach(() => {
215         jest.clearAllMocks();
216         jest.useFakeTimers();
218         const mockedDate = new Date(2023, 10, 1);
219         jest.setSystemTime(mockedDate);
220     });
222     afterEach(() => {
223         jest.useRealTimers();
224     });
226     describe('regular subscription renew', () => {
227         it('should render', () => {
228             const { container } = render(
229                 <RenewalNotice
230                     cycle={12}
231                     isCustomBilling={false}
232                     isScheduledSubscription={false}
233                     subscription={undefined}
234                     {...getProps()}
235                 />
236             );
237             expect(container).not.toBeEmptyDOMElement();
238         });
240         it('should display the correct renewal date', () => {
241             const renewCycle = 12;
242             const expectedDateString = '11/01/2024'; // because months are 0-indexed Â¯\_(ツ)_/¯
244             const { container } = render(
245                 <RenewalNotice
246                     cycle={renewCycle}
247                     isCustomBilling={false}
248                     isScheduledSubscription={false}
249                     subscription={undefined}
250                     {...getProps()}
251                 />
252             );
253             expect(container).toHaveTextContent(
254                 `Subscription auto-renews every 12 months. Your next billing date is ${expectedDateString}.`
255             );
256         });
258         it('should use period end date if custom billing is enabled', () => {
259             const renewCycle = 12;
260             const expectedDateString = '08/11/2025'; // because months are 0-indexed Â¯\_(ツ)_/¯
262             const { container } = render(
263                 <RenewalNotice
264                     cycle={renewCycle}
265                     isCustomBilling={true}
266                     isScheduledSubscription={false}
267                     subscription={
268                         {
269                             // the backend returns seconds, not milliseconds
270                             PeriodEnd: +new Date(2025, 7, 11) / 1000,
271                         } as any
272                     }
273                     {...getProps()}
274                 />
275             );
276             expect(container).toHaveTextContent(
277                 `Subscription auto-renews every 12 months. Your next billing date is ${expectedDateString}.`
278             );
279         });
281         it('should use the end of upcoming subscription period if scheduled subscription is enabled', () => {
282             const renewCycle = 24; // the upcoming subscription takes another 24 months
283             const { container } = render(
284                 <RenewalNotice
285                     cycle={renewCycle}
286                     isCustomBilling={false}
287                     isScheduledSubscription={true}
288                     subscription={
289                         {
290                             // the backend returns seconds, not milliseconds
291                             PeriodEnd: +new Date(2024, 1, 3) / 1000, // the current subscription period ends on 02/03/2024 (3rd of February 2024)
292                         } as any
293                     }
294                     {...getProps()}
295                 />
296             );
298             const expectedDateString = '02/03/2026'; // and finally the renewal date is 02/03/2026 (3rd of February 2026)
300             expect(container).toHaveTextContent(
301                 `Subscription auto-renews every 24 months. Your next billing date is ${expectedDateString}.`
302             );
303         });
305         it('should user the end of current subscription period if addon downgrade is enabled', () => {
306             // while addon downgrading also schedules subscription, it doesn't charge user immediately.
307             // User will be charged when the scheduled subscription starts.
308             // That's significant difference from scheduled subscription that charges user immediately.
310             const subscription: Subscription = {
311                 ID: 'Z1AOQDZSqE_rZEC01CXGl5fEy2JDRmT0M6WjSOtbvPep5lufR30jNAOKCcYavLK6rdOr_Wo4oID7UCskLdz0lw==',
312                 InvoiceID: 'HwphVYhz2wbcT2yQJGyumBEmSe5DJqagrgv-WfC4B9nhuUanbGgwGrVeydqE-e3KdpbkfAFrJ5-T5VF-_pTxyg==',
313                 Cycle: CYCLE.YEARLY,
314                 PeriodStart: 1718200044,
315                 PeriodEnd: 1749736044,
316                 CreateTime: 1718200044,
317                 CouponCode: null,
318                 Currency: 'CHF',
319                 Amount: 82443,
320                 Discount: -19485,
321                 RenewDiscount: 0,
322                 RenewAmount: 101928,
323                 Plans: [
324                     {
325                         ID: 'sId6XkzULCEzDPTuidkwWOgPInKjmzYJrw4nUYKnZHIwnlkiFqQjg_uHvzGrByCB99th0dfcVW-K5lK0E5tZmg==',
326                         Type: 1,
327                         Name: PLANS.BUNDLE_PRO_2024,
328                         Title: 'Proton Business Suite',
329                         MaxDomains: 15,
330                         MaxAddresses: 20,
331                         MaxCalendars: 25,
332                         MaxSpace: 536870912000,
333                         MaxMembers: 1,
334                         MaxVPN: 10,
335                         MaxTier: 2,
336                         Services: 15,
337                         Features: 1,
338                         State: 1,
339                         Cycle: 12,
340                         Currency: 'CHF',
341                         Amount: 15588,
342                         Offer: 'default',
343                         Quantity: 1,
344                     },
345                     {
346                         ID: 'vJF3r_xo_gpr-YfwAvEMwg3z1ZX7b4cTYHez1upZzszN3YWfQYjCdXQTnG4_WvXo7PJh-cIo1TGOBBKFrsFVoQ==',
347                         Type: 0,
348                         Name: ADDON_NAMES.DOMAIN_BUNDLE_PRO_2024,
349                         Title: '+1 Domain for Proton Business Suite',
350                         MaxDomains: 1,
351                         MaxAddresses: 0,
352                         MaxCalendars: 0,
353                         MaxSpace: 0,
354                         MaxMembers: 0,
355                         MaxVPN: 0,
356                         MaxTier: 0,
357                         Services: 15,
358                         Features: 0,
359                         State: 1,
360                         Cycle: 12,
361                         Currency: 'CHF',
362                         Amount: 1680,
363                         Quantity: 1,
364                     },
365                     {
366                         ID: 'vJF3r_xo_gpr-YfwAvEMwg3z1ZX7b4cTYHez1upZzszN3YWfQYjCdXQTnG4_WvXo7PJh-cIo1TGOBBKFrsFVoQ==',
367                         Type: 0,
368                         Name: ADDON_NAMES.DOMAIN_BUNDLE_PRO_2024,
369                         Title: '+1 Domain for Proton Business Suite',
370                         MaxDomains: 1,
371                         MaxAddresses: 0,
372                         MaxCalendars: 0,
373                         MaxSpace: 0,
374                         MaxMembers: 0,
375                         MaxVPN: 0,
376                         MaxTier: 0,
377                         Services: 15,
378                         Features: 0,
379                         State: 1,
380                         Cycle: 12,
381                         Currency: 'CHF',
382                         Amount: 1680,
383                         Quantity: 1,
384                     },
385                     {
386                         ID: 'vJF3r_xo_gpr-YfwAvEMwg3z1ZX7b4cTYHez1upZzszN3YWfQYjCdXQTnG4_WvXo7PJh-cIo1TGOBBKFrsFVoQ==',
387                         Type: 0,
388                         Name: ADDON_NAMES.DOMAIN_BUNDLE_PRO_2024,
389                         Title: '+1 Domain for Proton Business Suite',
390                         MaxDomains: 1,
391                         MaxAddresses: 0,
392                         MaxCalendars: 0,
393                         MaxSpace: 0,
394                         MaxMembers: 0,
395                         MaxVPN: 0,
396                         MaxTier: 0,
397                         Services: 15,
398                         Features: 0,
399                         State: 1,
400                         Cycle: 12,
401                         Currency: 'CHF',
402                         Amount: 1680,
403                         Quantity: 1,
404                     },
405                     {
406                         ID: 'vJF3r_xo_gpr-YfwAvEMwg3z1ZX7b4cTYHez1upZzszN3YWfQYjCdXQTnG4_WvXo7PJh-cIo1TGOBBKFrsFVoQ==',
407                         Type: 0,
408                         Name: ADDON_NAMES.DOMAIN_BUNDLE_PRO_2024,
409                         Title: '+1 Domain for Proton Business Suite',
410                         MaxDomains: 1,
411                         MaxAddresses: 0,
412                         MaxCalendars: 0,
413                         MaxSpace: 0,
414                         MaxMembers: 0,
415                         MaxVPN: 0,
416                         MaxTier: 0,
417                         Services: 15,
418                         Features: 0,
419                         State: 1,
420                         Cycle: 12,
421                         Currency: 'CHF',
422                         Amount: 1680,
423                         Quantity: 1,
424                     },
425                     {
426                         ID: 'vJF3r_xo_gpr-YfwAvEMwg3z1ZX7b4cTYHez1upZzszN3YWfQYjCdXQTnG4_WvXo7PJh-cIo1TGOBBKFrsFVoQ==',
427                         Type: 0,
428                         Name: ADDON_NAMES.DOMAIN_BUNDLE_PRO_2024,
429                         Title: '+1 Domain for Proton Business Suite',
430                         MaxDomains: 1,
431                         MaxAddresses: 0,
432                         MaxCalendars: 0,
433                         MaxSpace: 0,
434                         MaxMembers: 0,
435                         MaxVPN: 0,
436                         MaxTier: 0,
437                         Services: 15,
438                         Features: 0,
439                         State: 1,
440                         Cycle: 12,
441                         Currency: 'CHF',
442                         Amount: 1680,
443                         Quantity: 1,
444                     },
445                     {
446                         ID: '4bSUpHmMPr1NvKnJIIQQ_ZkhKqWe5TROcR_IFD0HhZxHaHJQrOZ7nw7H8eoLBbfhTWgw08BD4x5A81i3qJfgIA==',
447                         Type: 0,
448                         Name: ADDON_NAMES.MEMBER_BUNDLE_PRO_2024,
449                         Title: '+1 User for Proton Business Suite',
450                         MaxDomains: 0,
451                         MaxAddresses: 15,
452                         MaxCalendars: 25,
453                         MaxSpace: 536870912000,
454                         MaxMembers: 1,
455                         MaxVPN: 10,
456                         MaxTier: 0,
457                         Services: 15,
458                         Features: 0,
459                         State: 1,
460                         Cycle: 12,
461                         Currency: 'CHF',
462                         Amount: 15588,
463                         Offer: 'default',
464                         Quantity: 1,
465                     },
466                     {
467                         ID: '4bSUpHmMPr1NvKnJIIQQ_ZkhKqWe5TROcR_IFD0HhZxHaHJQrOZ7nw7H8eoLBbfhTWgw08BD4x5A81i3qJfgIA==',
468                         Type: 0,
469                         Name: ADDON_NAMES.MEMBER_BUNDLE_PRO_2024,
470                         Title: '+1 User for Proton Business Suite',
471                         MaxDomains: 0,
472                         MaxAddresses: 15,
473                         MaxCalendars: 25,
474                         MaxSpace: 536870912000,
475                         MaxMembers: 1,
476                         MaxVPN: 10,
477                         MaxTier: 0,
478                         Services: 15,
479                         Features: 0,
480                         State: 1,
481                         Cycle: 12,
482                         Currency: 'CHF',
483                         Amount: 15588,
484                         Offer: 'default',
485                         Quantity: 1,
486                     },
487                     {
488                         ID: '4bSUpHmMPr1NvKnJIIQQ_ZkhKqWe5TROcR_IFD0HhZxHaHJQrOZ7nw7H8eoLBbfhTWgw08BD4x5A81i3qJfgIA==',
489                         Type: 0,
490                         Name: ADDON_NAMES.MEMBER_BUNDLE_PRO_2024,
491                         Title: '+1 User for Proton Business Suite',
492                         MaxDomains: 0,
493                         MaxAddresses: 15,
494                         MaxCalendars: 25,
495                         MaxSpace: 536870912000,
496                         MaxMembers: 1,
497                         MaxVPN: 10,
498                         MaxTier: 0,
499                         Services: 15,
500                         Features: 0,
501                         State: 1,
502                         Cycle: 12,
503                         Currency: 'CHF',
504                         Amount: 15588,
505                         Offer: 'default',
506                         Quantity: 1,
507                     },
508                     {
509                         ID: '4bSUpHmMPr1NvKnJIIQQ_ZkhKqWe5TROcR_IFD0HhZxHaHJQrOZ7nw7H8eoLBbfhTWgw08BD4x5A81i3qJfgIA==',
510                         Type: 0,
511                         Name: ADDON_NAMES.MEMBER_BUNDLE_PRO_2024,
512                         Title: '+1 User for Proton Business Suite',
513                         MaxDomains: 0,
514                         MaxAddresses: 15,
515                         MaxCalendars: 25,
516                         MaxSpace: 536870912000,
517                         MaxMembers: 1,
518                         MaxVPN: 10,
519                         MaxTier: 0,
520                         Services: 15,
521                         Features: 0,
522                         State: 1,
523                         Cycle: 12,
524                         Currency: 'CHF',
525                         Amount: 15588,
526                         Offer: 'default',
527                         Quantity: 1,
528                     },
529                     {
530                         ID: '4bSUpHmMPr1NvKnJIIQQ_ZkhKqWe5TROcR_IFD0HhZxHaHJQrOZ7nw7H8eoLBbfhTWgw08BD4x5A81i3qJfgIA==',
531                         Type: 0,
532                         Name: ADDON_NAMES.MEMBER_BUNDLE_PRO_2024,
533                         Title: '+1 User for Proton Business Suite',
534                         MaxDomains: 0,
535                         MaxAddresses: 15,
536                         MaxCalendars: 25,
537                         MaxSpace: 536870912000,
538                         MaxMembers: 1,
539                         MaxVPN: 10,
540                         MaxTier: 0,
541                         Services: 15,
542                         Features: 0,
543                         State: 1,
544                         Cycle: 12,
545                         Currency: 'CHF',
546                         Amount: 15588,
547                         Offer: 'default',
548                         Quantity: 1,
549                     },
550                 ],
551                 Renew: 1,
552                 External: 0,
553                 BillingPlatform: 1,
554                 IsTrial: false,
555             };
557             const { container } = render(
558                 <RenewalNotice
559                     {...getProps()}
560                     cycle={CYCLE.YEARLY}
561                     isCustomBilling={false}
562                     isScheduledSubscription={false}
563                     isAddonDowngrade={true}
564                     isProration={false}
565                     planIDs={{ bundlepro2024: 1, '1domain-bundlepro2024': 5, '1member-bundlepro2024': 5 }}
566                     subscription={subscription}
567                 />
568             );
570             // end of the current subscription, NOT upcoming that will be created when user accepts the terms of AddonDowngrade subscription
571             const expectedDateString = '06/12/2025';
573             expect(container).toHaveTextContent(
574                 `Subscription auto-renews every 12 months. Your next billing date is ${expectedDateString}.`
575             );
576         });
577     });
579     describe('vpn2024 special renew cycle', () => {
580         [CYCLE.TWO_YEARS, CYCLE.YEARLY, CYCLE.FIFTEEN, CYCLE.THIRTY].forEach((cycle) => {
581             it(`should display special renewal notice for vpn2024 ${cycle} months`, () => {
582                 const { container } = render(
583                     <RenewalNotice
584                         {...getProps({ planIDs: { [PLANS.VPN2024]: 1 }, checkResult: getFreeCheckResult() })}
585                         cycle={cycle}
586                     />
587                 );
589                 expect(container).toHaveTextContent(
590                     `Your subscription will automatically renew in ${cycle} months. You'll then be billed every 12 months at CHF 79.95.`
591                 );
592             });
593         });
595         [CYCLE.THREE, CYCLE.MONTHLY].forEach((cycle) => {
596             it(`should display special renewal notice for vpn2024 ${cycle} months`, () => {
597                 const { container } = render(
598                     <RenewalNotice
599                         {...getProps({ planIDs: { [PLANS.VPN2024]: 1 }, checkResult: getFreeCheckResult() })}
600                         cycle={cycle}
601                     />
602                 );
604                 if (cycle != CYCLE.MONTHLY) {
605                     const nextDate = addMonths(new Date(), cycle);
606                     expect(container).toHaveTextContent(
607                         `Subscription auto-renews every ${cycle} months. Your next billing date is ${(nextDate.getMonth() + 1).toString().padStart(2, '0')}/${nextDate.getDate().toString().padStart(2, '0')}/${nextDate.getFullYear()}.`
608                     );
609                 } else {
610                     expect(container).toHaveTextContent(
611                         `Subscription auto-renews every month. Your next billing date is 12/01/2023.`
612                     );
613                 }
614             });
615         });
616     });
618     describe('one time coupons', () => {
619         [CYCLE.TWO_YEARS, CYCLE.YEARLY, CYCLE.FIFTEEN, CYCLE.THIRTY].forEach((cycle) => {
620             it(`should ignore coupon for vpn2024 with a coupon`, () => {
621                 const { container } = render(
622                     <RenewalNotice
623                         {...getProps({
624                             planIDs: { [PLANS.VPN2024]: 1 },
625                             checkResult: {
626                                 Amount: 11976,
627                                 AmountDue: 10776,
628                                 Proration: 0,
629                                 CouponDiscount: -1200,
630                                 Gift: 0,
631                                 Credit: 0,
632                                 Coupon: {
633                                     Code: 'VPNINTROPRICE2024',
634                                     Description: 'Introductory price for VPN Plus',
635                                     MaximumRedemptionsPerUser: 1,
636                                 },
637                                 Cycle: 24,
638                                 TaxInclusive: 1,
639                                 Taxes: [
640                                     {
641                                         Name: 'Mehrwertsteuer (MWST)',
642                                         Rate: 8.0999999999999996,
643                                         Amount: 807,
644                                     },
645                                 ],
646                                 Currency: 'CHF',
647                             },
648                         })}
649                         cycle={cycle}
650                     />
651                 );
653                 expect(container).toHaveTextContent(
654                     `Your subscription will automatically renew in ${cycle} months. You'll then be billed every 12 months at CHF 79.95.`
655                 );
656             });
657         });
659         it(`should apply it for 12m vpnpass bundle`, () => {
660             const { container } = render(
661                 <RenewalNotice
662                     {...getProps({
663                         planIDs: { [PLANS.VPN_PASS_BUNDLE]: 1 },
664                         checkResult: {
665                             Amount: 10395,
666                             AmountDue: 4788,
667                             Proration: 0,
668                             CouponDiscount: -5607,
669                             Gift: 0,
670                             Credit: 0,
671                             Coupon: {
672                                 Code: 'TECHRADARVPNPASS',
673                                 Description: '',
674                                 MaximumRedemptionsPerUser: 1,
675                             },
676                             Cycle: CYCLE.YEARLY,
677                             TaxInclusive: 1,
678                             Taxes: [
679                                 {
680                                     Name: 'Mehrwertsteuer (MWST)',
681                                     Rate: 8.0999999999999996,
682                                     Amount: 359,
683                                 },
684                             ],
685                             Currency: 'CHF',
686                         },
687                     })}
688                     cycle={CYCLE.YEARLY}
689                 />
690             );
692             expect(container).toHaveTextContent(
693                 'The specially discounted price of CHF 47.88 is valid for the first 12 months. Then it will automatically be renewed at CHF 95.88 for 12 months. You can cancel at any time.'
694             );
695         });
697         it(`should apply it for 1m mail offer`, () => {
698             const { container } = render(
699                 <RenewalNotice
700                     {...getProps({
701                         planIDs: { [PLANS.MAIL]: 1 },
702                         checkResult: {
703                             Amount: 499,
704                             AmountDue: 100,
705                             Proration: 0,
706                             CouponDiscount: -399,
707                             Gift: 0,
708                             Credit: 0,
709                             Coupon: {
710                                 Code: 'MAILPLUSINTRO',
711                                 Description: 'MAILPLUSINTRO',
712                                 MaximumRedemptionsPerUser: 1,
713                             },
714                             Cycle: 1,
715                             TaxInclusive: 1,
716                             Taxes: [
717                                 {
718                                     Name: 'Mehrwertsteuer (MWST)',
719                                     Rate: 8.0999999999999996,
720                                     Amount: 7,
721                                 },
722                             ],
723                             Currency: 'CHF',
724                         },
725                     })}
726                     cycle={CYCLE.MONTHLY}
727                 />
728             );
729             expect(container).toHaveTextContent(
730                 'The specially discounted price of CHF 1 is valid for the first month. Then it will automatically be renewed at CHF 4.99 every month. You can cancel at any time.'
731             );
732         });
733     });
736 describe('getPassLifetimeRenewNoticeText', () => {
737     it('should show basic lifetime message when no subscription exists', () => {
738         const { container } = render(
739             <RenewalNotice
740                 {...getProps()}
741                 cycle={CYCLE.YEARLY}
742                 subscription={undefined}
743                 planIDs={{ [PLANS.PASS_LIFETIME]: 1 }}
744             />
745         );
747         expect(container).toHaveTextContent(
748             "Pass lifetime deal has no renewal price, it's a one-time payment for lifetime access to Pass."
749         );
750     });
752     it('should show basic lifetime message for free plan', () => {
753         const subscription = {
754             Plans: [
755                 {
756                     Name: PLANS.FREE,
757                 },
758             ],
759         } as Subscription;
761         const { container } = render(
762             <RenewalNotice
763                 {...getProps()}
764                 cycle={CYCLE.YEARLY}
765                 subscription={subscription}
766                 planIDs={{ [PLANS.PASS_LIFETIME]: 1 }}
767             />
768         );
770         expect(container).toHaveTextContent(
771             "Pass lifetime deal has no renewal price, it's a one-time payment for lifetime access to Pass."
772         );
773     });
775     it('should show replacement message for Pass Plus subscribers', () => {
776         const subscription = {
777             Plans: [
778                 {
779                     Type: PLAN_TYPES.PLAN,
780                     Name: PLANS.PASS,
781                 },
782             ],
783         } as Subscription;
785         const { container } = render(
786             <RenewalNotice
787                 {...getProps()}
788                 cycle={CYCLE.YEARLY}
789                 subscription={subscription}
790                 planIDs={{ [PLANS.PASS_LIFETIME]: 1 }}
791             />
792         );
794         expect(container).toHaveTextContent(
795             "Your Pass Plus subscription will be replaced with Pass Lifetime. The remaining balance of your subscription will be added to your account. Pass lifetime deal has no renewal price, it's a one-time payment for lifetime access to Pass."
796         );
797     });
799     it('should show unchanged subscription message for other plan subscribers', () => {
800         const subscription = {
801             Plans: [
802                 {
803                     Type: PLAN_TYPES.PLAN,
804                     Name: PLANS.MAIL,
805                     Title: 'Mail Plus',
806                 },
807             ],
808         } as Subscription;
810         const { container } = render(
811             <RenewalNotice
812                 {...getProps()}
813                 cycle={CYCLE.YEARLY}
814                 subscription={subscription}
815                 planIDs={{ [PLANS.PASS_LIFETIME]: 1 }}
816             />
817         );
819         expect(container).toHaveTextContent(
820             "Pass lifetime deal has no renewal price, it's a one-time payment for lifetime access to Pass. Your Mail Plus subscription renewal price and date remain unchanged."
821         );
822     });