Skip to content

Commit

Permalink
Merge pull request #66 from xsolla/PAYMENTS-18110
Browse files Browse the repository at this point in the history
feat (PAYMENTS-18110): add combined payment methods
  • Loading branch information
ekireevxs authored Mar 18, 2024
2 parents 52ab7f3 + 997bb4c commit ff95bab
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 9 deletions.
10 changes: 10 additions & 0 deletions src/core/combined-payment-methods.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { PaymentMethod } from './payment-method.interface';
import { SavedMethod } from './saved-method.interface';

export interface CombinedPaymentMethods {
paymentMethods: {
quick: PaymentMethod[];
remained: PaymentMethod[];
};
savedMethods: SavedMethod[];
}
1 change: 1 addition & 0 deletions src/core/event-name.enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export const enum EventName {
submitForm = 'submitForm',
getPaymentMethodsList = 'getPaymentMethodsList',
getPaymentQuickMethods = 'getPaymentQuickMethods',
getCombinedPaymentMethods = 'getCombinedPaymentMethods',
getSavedMethods = 'getSavedMethods',
getUserBalance = 'getUserBalance',
getUserBalanceValue = 'getUserBalanceValue',
Expand Down
22 changes: 22 additions & 0 deletions src/core/guards/combined-payment-methods-event-message.guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Message } from '../../core/message.interface';
import { isEventMessage } from './event-message.guard';
import { EventName } from '../../core/event-name.enum';
import { CombinedPaymentMethods } from '../combined-payment-methods.interface';

export const isCombinedMethodsEventMessage = (
messageData: unknown,
): messageData is Message<{
combinedPaymentMethods: CombinedPaymentMethods;
}> => {
if (isEventMessage(messageData)) {
return (
messageData.name === EventName.getCombinedPaymentMethods &&
!!(
messageData.data as {
[key: string]: unknown;
}
)?.combinedPaymentMethods
);
}
return false;
};
24 changes: 15 additions & 9 deletions src/features/headless-checkout/headless-checkout.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ describe('HeadlessCheckout', () => {
origin: headlessCheckoutAppUrl,
data: JSON.stringify({ name: EventName.isReady }),
} as MessageEvent);
}
},
);
postMessagesClient = {
init: stub,
Expand Down Expand Up @@ -83,7 +83,7 @@ describe('HeadlessCheckout', () => {
const spy = spyOn(postMessagesClient, 'init');
spyOn(windowService.document.body, 'appendChild');
spyOn(windowService.document, 'createElement').and.callFake(
() => new MockIframeElement() as unknown as HTMLIFrameElement
() => new MockIframeElement() as unknown as HTMLIFrameElement,
);
await headlessCheckout.init({ isWebview: false });
expect(spy).toHaveBeenCalled();
Expand All @@ -92,7 +92,7 @@ describe('HeadlessCheckout', () => {
it('Should init localization', () => {
const localizeSpy = spyOn(
localizeService,
'initDictionaries'
'initDictionaries',
).and.resolveTo();

void headlessCheckout.init({ isWebview: false });
Expand All @@ -111,7 +111,7 @@ describe('HeadlessCheckout', () => {
headlessCheckout.events.onCoreEvent(
EventName.initPayment,
mockHandler,
stub
stub,
);
expect(spy).toHaveBeenCalled();
});
Expand All @@ -120,7 +120,7 @@ describe('HeadlessCheckout', () => {
const spy = spyOn(postMessagesClient, 'listen');
spyOn(windowService.document.body, 'appendChild');
spyOn(windowService.document, 'createElement').and.callFake(
() => new MockIframeElement() as unknown as HTMLIFrameElement
() => new MockIframeElement() as unknown as HTMLIFrameElement,
);

await headlessCheckout.init({ isWebview: false });
Expand Down Expand Up @@ -152,7 +152,7 @@ describe('HeadlessCheckout', () => {
await headlessCheckout.getFinanceDetails();
expect(spy).toHaveBeenCalledWith(
{ name: EventName.financeDetails },
getFinanceDetailsHandler
getFinanceDetailsHandler,
);
});

Expand All @@ -168,12 +168,18 @@ describe('HeadlessCheckout', () => {
expect(spy).toHaveBeenCalled();
});

it('Should getCombinedPaymentMethods', async () => {
const spy = spyOn(postMessagesClient, 'send').and.stub();
await headlessCheckout.getCombinedPaymentMethods();
expect(spy).toHaveBeenCalled();
});

it('Should correctly define web components', async () => {
const spy = spyOn(windowService.customElements, 'define');
spyOn(windowService.customElements, 'get').and.returnValue(undefined);
spyOn(windowService.document.body, 'appendChild');
spyOn(windowService.document, 'createElement').and.callFake(
() => new MockIframeElement() as unknown as HTMLIFrameElement
() => new MockIframeElement() as unknown as HTMLIFrameElement,
);

await headlessCheckout.init({ isWebview: false });
Expand All @@ -182,11 +188,11 @@ describe('HeadlessCheckout', () => {

it('Should web components not be redefined', async () => {
spyOn(windowService.customElements, 'get').and.returnValue(
CustomElementMock
CustomElementMock,
);
spyOn(windowService.document.body, 'appendChild');
spyOn(windowService.document, 'createElement').and.callFake(
() => new MockIframeElement() as unknown as HTMLIFrameElement
() => new MockIframeElement() as unknown as HTMLIFrameElement,
);

const spy = spyOn(window.customElements, 'define');
Expand Down
13 changes: 13 additions & 0 deletions src/features/headless-checkout/headless-checkout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ import { FormStatus } from '../../core/status/form-status.enum';
import { setSecureComponentStylesHandler } from './post-messages-handlers/set-secure-component-styles.handler';
import { formFieldsStatusChangedHandler } from './post-messages-handlers/form-fields-status-changed.handler';
import { FormFieldsStatus } from '../../core/form/form-fields-status.interface';
import { getCombinedPaymentMethodsHandler } from './post-messages-handlers/get-combined-payment-methods.handler';
import { CombinedPaymentMethods } from '../../core/combined-payment-methods.interface';

@singleton()
export class HeadlessCheckout {
Expand Down Expand Up @@ -270,6 +272,17 @@ export class HeadlessCheckout {
) as Promise<PaymentMethod[]>;
}

public async getCombinedPaymentMethods(): Promise<CombinedPaymentMethods> {
const msg: Message = {
name: EventName.getCombinedPaymentMethods,
};

return this.postMessagesClient.send<CombinedPaymentMethods>(
msg,
getCombinedPaymentMethodsHandler,
) as Promise<CombinedPaymentMethods>;
}

public async getSavedMethods(): Promise<SavedMethod[]> {
const msg: Message = {
name: EventName.getSavedMethods,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Handler } from '../../../core/post-messages-client/handler.type';
import { Message } from '../../../core/message.interface';
import { isCombinedMethodsEventMessage } from '../../../core/guards/combined-payment-methods-event-message.guard';
import { CombinedPaymentMethods } from '../../../core/combined-payment-methods.interface';

export const getCombinedPaymentMethodsHandler: Handler<
CombinedPaymentMethods
> = (
message: Message,
): { isHandled: boolean; value: CombinedPaymentMethods } | null => {
if (!isCombinedMethodsEventMessage(message)) {
return null;
}

const combinedPaymentMethods = message.data?.combinedPaymentMethods;
return {
isHandled: true,
value: combinedPaymentMethods as unknown as CombinedPaymentMethods,
};
};

0 comments on commit ff95bab

Please sign in to comment.