Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v6 All UIElements can receive defaultProps based on regulations #2546

Merged
merged 5 commits into from
Feb 16, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions packages/lib/src/components/Dropin/Dropin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,14 @@ describe('Dropin', () => {
});
});

// TODO - this test doesn't do anything
sponglord marked this conversation as resolved.
Show resolved Hide resolved
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();
Expand Down Expand Up @@ -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);
});
});
});
3 changes: 2 additions & 1 deletion packages/lib/src/components/Dropin/Dropin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 { IDropin } from './types';
sponglord marked this conversation as resolved.
Show resolved Hide resolved

const SUPPORTED_INSTANT_PAYMENTS = ['paywithgoogle', 'googlepay', 'applepay'];

class DropinElement extends UIElement<DropinConfiguration> {
class DropinElement extends UIElement<DropinConfiguration> implements IDropin {
protected static defaultProps = defaultProps;

public dropinRef = null;
Expand Down
5 changes: 5 additions & 0 deletions packages/lib/src/components/Dropin/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,8 @@ export interface DropinComponentState {
isDisabling: boolean;
orderStatus: OrderStatus;
}

export interface IDropin {
activePaymentMethod: () => null;
closeActivePaymentMethod: () => void;
}
11 changes: 9 additions & 2 deletions packages/lib/src/components/internal/UIElement/UIElement.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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';

Expand Down Expand Up @@ -83,7 +84,13 @@ export abstract class UIElement<P extends UIElementProps = UIElementProps> 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) {
Expand Down
23 changes: 23 additions & 0 deletions packages/lib/src/components/internal/UIElement/utils.ts
Original file line number Diff line number Diff line change
@@ -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'];

Expand Down Expand Up @@ -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<string, any> {
switch (countryCode) {
// Finnish regulations state that no payment method can be open by default
case 'FI':
return isDropin
? {
openFirstPaymentMethod: false,
openFirstStoredPaymentMethod: false
}
: {};
default:
return {};
}
}
Loading