diff --git a/packages/lib/src/components/Dropin/Dropin.test.ts b/packages/lib/src/components/Dropin/Dropin.test.ts index 48bde47149..c80058437e 100644 --- a/packages/lib/src/components/Dropin/Dropin.test.ts +++ b/packages/lib/src/components/Dropin/Dropin.test.ts @@ -38,12 +38,14 @@ describe('Dropin', () => { }); }); + // TODO - this test doesn't do anything describe('closeActivePaymentMethod', () => { test('should close active payment method', async () => { const dropin = new Dropin(checkout); const component = await mount(dropin.render()); await component.update(); + // re. TODO: dropin.dropinRef.state.activePaymentMethod = null, which is defined, so this assertion passes expect(dropin.dropinRef.state.activePaymentMethod).toBeDefined(); dropin.closeActivePaymentMethod(); expect(dropin.dropinRef.state.activePaymentMethod).toBeNull(); @@ -155,4 +157,31 @@ describe('Dropin', () => { expect(await screen.findByText(/An unknown error occurred/i)).toBeTruthy(); }); }); + + describe('Complying with local regulations', () => { + test('Default values for openFirstPaymentMethod & openFirstStoredPaymentMethod are true', () => { + const dropin = new Dropin(checkout); + + expect(dropin.props.openFirstPaymentMethod).toBe(true); + expect(dropin.props.openFirstStoredPaymentMethod).toBe(true); + }); + + test('when countryCode is Finland openFirstPaymentMethod & openFirstStoredPaymentMethod should be false by default', () => { + checkout.options.countryCode = 'FI'; + + const dropin = new Dropin(checkout); + + expect(dropin.props.openFirstPaymentMethod).toBe(false); + expect(dropin.props.openFirstStoredPaymentMethod).toBe(false); + }); + + test('if openFirstPaymentMethod & openFirstStoredPaymentMethod are set by merchant then these values should be used', () => { + checkout.options.countryCode = 'FI'; + + const dropin = new Dropin(checkout, { openFirstPaymentMethod: true, openFirstStoredPaymentMethod: true }); + + expect(dropin.props.openFirstPaymentMethod).toBe(true); + expect(dropin.props.openFirstStoredPaymentMethod).toBe(true); + }); + }); }); diff --git a/packages/lib/src/components/Dropin/Dropin.tsx b/packages/lib/src/components/Dropin/Dropin.tsx index 3654962d8f..a05b0a833f 100644 --- a/packages/lib/src/components/Dropin/Dropin.tsx +++ b/packages/lib/src/components/Dropin/Dropin.tsx @@ -12,10 +12,11 @@ import { hasOwnProperty } from '../../utils/hasOwnProperty'; import SRPanelProvider from '../../core/Errors/SRPanelProvider'; import splitPaymentMethods from './elements/splitPaymentMethods'; import type { ICore } from '../../core/types'; +import type { IDropin } from './types'; const SUPPORTED_INSTANT_PAYMENTS = ['paywithgoogle', 'googlepay', 'applepay']; -class DropinElement extends UIElement { +class DropinElement extends UIElement implements IDropin { protected static defaultProps = defaultProps; public dropinRef = null; diff --git a/packages/lib/src/components/Dropin/types.ts b/packages/lib/src/components/Dropin/types.ts index aa4700459f..4f2a0d9473 100644 --- a/packages/lib/src/components/Dropin/types.ts +++ b/packages/lib/src/components/Dropin/types.ts @@ -124,3 +124,8 @@ export interface DropinComponentState { isDisabling: boolean; orderStatus: OrderStatus; } + +export interface IDropin { + activePaymentMethod: () => null; + closeActivePaymentMethod: () => void; +} diff --git a/packages/lib/src/components/internal/UIElement/UIElement.tsx b/packages/lib/src/components/internal/UIElement/UIElement.tsx index 5def86c1c6..09fb6eb803 100644 --- a/packages/lib/src/components/internal/UIElement/UIElement.tsx +++ b/packages/lib/src/components/internal/UIElement/UIElement.tsx @@ -1,7 +1,7 @@ import { h } from 'preact'; import BaseElement from '../BaseElement/BaseElement'; import PayButton from '../PayButton'; -import { cleanupFinalResult, sanitizeResponse, verifyPaymentDidNotFail } from './utils'; +import { assertIsDropin, cleanupFinalResult, getRegulatoryDefaults, sanitizeResponse, verifyPaymentDidNotFail } from './utils'; import AdyenCheckoutError from '../../../core/Errors/AdyenCheckoutError'; import { hasOwnProperty } from '../../../utils/hasOwnProperty'; import { Resources } from '../../../core/Context/Resources'; @@ -22,6 +22,7 @@ import type { } from '../../../types/global-types'; import { ANALYTICS_SUBMIT_STR } from '../../../core/Analytics/constants'; import { AnalyticsInitialEvent, SendAnalyticsObject } from '../../../core/Analytics/types'; +import { IDropin } from '../../Dropin/types'; import './UIElement.scss'; @@ -83,7 +84,13 @@ export abstract class UIElement

exten ...componentProps }; - this.props = this.formatProps({ ...this.constructor['defaultProps'], ...finalProps }); + const isDropin = assertIsDropin(this as unknown as IDropin); + + this.props = this.formatProps({ + ...this.constructor['defaultProps'], // component defaults + ...getRegulatoryDefaults(this.core.options.countryCode, isDropin), // regulatory defaults + ...finalProps // the rest (inc. merchant defined config) + }); } protected storeElementRefOnCore(props?: P) { diff --git a/packages/lib/src/components/internal/UIElement/utils.ts b/packages/lib/src/components/internal/UIElement/utils.ts index a22461a00c..57ac261567 100644 --- a/packages/lib/src/components/internal/UIElement/utils.ts +++ b/packages/lib/src/components/internal/UIElement/utils.ts @@ -1,5 +1,6 @@ import { UIElementStatus } from './types'; import { RawPaymentResponse, PaymentResponseData } from '../../../types/global-types'; +import { IDropin } from '../../Dropin/types'; const ALLOWED_PROPERTIES = ['action', 'resultCode', 'sessionData', 'order', 'sessionResult', 'donationToken', 'error']; @@ -57,3 +58,25 @@ export function verifyPaymentDidNotFail(response: PaymentResponseData): Promise< return Promise.resolve(response); } + +export function assertIsDropin(dropin: IDropin) { + if (!dropin) return false; + + const isDropin = typeof dropin.activePaymentMethod === 'object' && typeof dropin.closeActivePaymentMethod === 'function'; + return isDropin; +} + +export function getRegulatoryDefaults(countryCode: string, isDropin: boolean): Record { + switch (countryCode) { + // Finnish regulations state that no payment method can be open by default + case 'FI': + return isDropin + ? { + openFirstPaymentMethod: false, + openFirstStoredPaymentMethod: false + } + : {}; + default: + return {}; + } +}