1 import { fireEvent } from '@testing-library/dom';
5 ChargebeeSubmitEventResponse,
7 GetHeightResponsePayload,
10 PaypalAuthorizedPayload,
11 ThreeDsChallengePayload,
13 import { chargebeeWrapperVersion } from './checkpoints';
16 DirectDebitSubmitEvent,
20 SetConfigurationEvent,
21 SetPaypalPaymentIntentEvent,
24 } from './message-bus';
25 import { MessageBus, createMessageBus, getMessageBus, verifySavedCardMessageType } from './message-bus';
27 window.parent.postMessage = jest.fn();
29 let messageBus: MessageBus | null = null;
33 const config: ParentMessagesProps = {
34 onSetConfiguration: jest.fn(),
36 onSetPaypalPaymentIntent: jest.fn(),
37 onGetHeight: jest.fn(),
39 onValidateForm: jest.fn(),
40 onVerifySavedCard: jest.fn(),
43 createMessageBus(config);
45 messageBus = getMessageBus();
48 it('should create message bus', () => {
49 const messageBus = getMessageBus();
50 expect(messageBus).toBeInstanceOf(MessageBus);
53 it('should listen to set configuration event', () => {
54 const event: SetConfigurationEvent = {
55 type: 'set-configuration',
56 correlationId: 'id-1',
57 paymentMethodType: 'card',
62 '--signal-danger': '#000000',
63 '--border-radius-md': '#000000',
64 '--border-norm': '#000000',
65 '--focus-outline': '#000000',
66 '--focus-ring': '#000000',
67 '--field-norm': '#000000',
68 '--field-background-color': '#000000',
69 '--field-focus-background-color': '#000000',
70 '--field-focus-text-color': '#000000',
71 '--field-placeholder-color': '#000000',
72 '--field-text-color': '#000000',
73 '--selection-text-color': '#000000',
74 '--selection-background-color': '#000000',
77 cardNumberPlaceholder: '0000 0000 0000 0000',
78 cardExpiryPlaceholder: 'MM/YY',
79 cardCvcPlaceholder: '000',
80 invalidCardNumberMessage: 'Invalid card number',
81 invalidCardExpiryMessage: 'Invalid card expiry',
82 invalidCardCvcMessage: 'Invalid card cvc',
84 renderMode: 'one-line',
89 new MessageEvent('message', {
93 expect(messageBus?.onSetConfiguration).toHaveBeenCalled();
94 const firstArg = (messageBus?.onSetConfiguration as jest.Mock).mock.calls[0][0];
95 expect(firstArg).toEqual(event);
97 const secondArg = (messageBus?.onSetConfiguration as jest.Mock).mock.calls[0][1];
98 expect(secondArg).toBeInstanceOf(Function);
100 const response: MessageBusResponse<{}> = {
105 expect(window.parent.postMessage).toHaveBeenCalledWith(
107 type: 'set-configuration-response',
108 correlationId: event.correlationId,
116 it('should listen to submit event', () => {
117 const event: ChargebeeSubmitEvent = {
118 type: 'chargebee-submit',
119 correlationId: 'id-1',
121 type: 'payment_intent',
129 new MessageEvent('message', {
134 expect(messageBus?.onSubmit).toHaveBeenCalled();
135 const firstArg = (messageBus?.onSubmit as jest.Mock).mock.calls[0][0];
136 expect(firstArg).toEqual(event);
138 const secondArg = (messageBus?.onSubmit as jest.Mock).mock.calls[0][1];
139 expect(secondArg).toBeInstanceOf(Function);
141 const response: MessageBusResponse<{}> = {
146 expect(window.parent.postMessage).toHaveBeenCalledWith(
148 type: 'chargebee-submit-response',
149 correlationId: event.correlationId,
157 it('should listen to set paypal payment intent event', () => {
158 const event: SetPaypalPaymentIntentEvent = {
159 type: 'set-paypal-payment-intent',
160 correlationId: 'id-1',
162 type: 'payment_intent',
165 // todo: perhaps remove it
172 new MessageEvent('message', {
177 expect(messageBus?.onSetPaypalPaymentIntent).toHaveBeenCalled();
178 const firstArg = (messageBus?.onSetPaypalPaymentIntent as jest.Mock).mock.calls[0][0];
179 expect(firstArg).toEqual(event);
181 const secondArg = (messageBus?.onSetPaypalPaymentIntent as jest.Mock).mock.calls[0][1];
182 expect(secondArg).toBeInstanceOf(Function);
184 const response: MessageBusResponse<ChargebeeSubmitEventResponse> = {
188 approvalUrl: 'https://proton.me',
189 } as any, // todo: fix types
193 expect(window.parent.postMessage).toHaveBeenCalledWith(
195 type: 'set-paypal-payment-intent-response',
196 correlationId: event.correlationId,
200 approvalUrl: 'https://proton.me',
207 it('should listen to get height event', () => {
208 const event: GetHeightEvent = {
210 correlationId: 'id-1',
215 new MessageEvent('message', {
220 expect(messageBus?.onGetHeight).toHaveBeenCalled();
221 const firstArg = (messageBus?.onGetHeight as jest.Mock).mock.calls[0][0];
222 expect(firstArg).toEqual(event);
224 const secondArg = (messageBus?.onGetHeight as jest.Mock).mock.calls[0][1];
225 expect(secondArg).toBeInstanceOf(Function);
227 const response: MessageBusResponse<GetHeightResponsePayload> = {
235 expect(window.parent.postMessage).toHaveBeenCalledWith(
237 type: 'get-height-response',
238 correlationId: event.correlationId,
249 it('should listen to get bin event', () => {
250 const event: GetBinEvent = {
252 correlationId: 'id-1',
257 new MessageEvent('message', {
262 expect(messageBus?.onGetBin).toHaveBeenCalled();
263 const firstArg = (messageBus?.onGetBin as jest.Mock).mock.calls[0][0];
264 expect(firstArg).toEqual(event);
266 const secondArg = (messageBus?.onGetBin as jest.Mock).mock.calls[0][1];
267 expect(secondArg).toBeInstanceOf(Function);
269 const response: MessageBusResponse<BinData> = {
278 expect(window.parent.postMessage).toHaveBeenCalledWith(
280 type: 'get-bin-response',
281 correlationId: event.correlationId,
288 it('should listen to validate form event', () => {
289 const event: ValidateFormEvent = {
290 type: 'validate-form',
291 correlationId: 'id-1',
296 new MessageEvent('message', {
301 expect(messageBus?.onValidateForm).toHaveBeenCalled();
302 const firstArg = (messageBus?.onValidateForm as jest.Mock).mock.calls[0][0];
303 expect(firstArg).toEqual(event);
305 const secondArg = (messageBus?.onValidateForm as jest.Mock).mock.calls[0][1];
306 expect(secondArg).toBeInstanceOf(Function);
308 const response: MessageBusResponse<FormValidationErrors> = {
315 expect(window.parent.postMessage).toHaveBeenCalledWith(
317 type: 'validate-form-response',
318 correlationId: event.correlationId,
326 it('should listen to verify saved card event', () => {
327 const event: VerifySavedCardEvent = {
328 type: verifySavedCardMessageType,
329 correlationId: 'id-1',
331 type: 'payment_intent',
337 new MessageEvent('message', {
342 expect(messageBus?.onVerifySavedCard).toHaveBeenCalled();
344 const firstArg = (messageBus?.onVerifySavedCard as jest.Mock).mock.calls[0][0];
345 expect(firstArg).toEqual(event);
347 const secondArg = (messageBus?.onVerifySavedCard as jest.Mock).mock.calls[0][1];
348 expect(secondArg).toBeInstanceOf(Function);
350 const response: MessageBusResponse<ChargebeeSubmitEventResponse> = {
354 approvalUrl: 'https://proton.me',
355 } as any, // todo: fix types
359 expect(window.parent.postMessage).toHaveBeenCalledWith(
361 type: 'chargebee-verify-saved-card-response',
362 correlationId: event.correlationId,
366 approvalUrl: 'https://proton.me',
373 it('should send paypal authorized message', () => {
374 const data: PaypalAuthorizedPayload = {
376 type: 'payment_intent',
380 messageBus?.sendPaypalAuthorizedMessage(data);
381 const expectedMessage = {
386 expect(window.parent.postMessage).toHaveBeenCalledWith(
388 type: 'paypal-authorized',
395 it('should send 3ds challenge message', () => {
396 const data: ThreeDsChallengePayload = {
397 url: 'https://proton.me',
400 const correlationId = 'id-1';
402 messageBus?.send3dsChallengeMessage(data, correlationId);
403 const expectedMessage = {
409 expect(window.parent.postMessage).toHaveBeenCalledWith(
411 type: '3ds-challenge',
418 it('should send 3ds failed message', () => {
423 const correlationId = 'id-1';
425 messageBus?.send3dsFailedMessage(error, correlationId);
426 const expectedMessage = {
432 expect(window.parent.postMessage).toHaveBeenCalledWith(
434 type: 'chargebee-submit-response',
441 it('should send form validation error message', () => {
442 const errors: FormValidationErrors = [
449 const correlationId = 'id-1';
451 messageBus?.sendFormValidationErrorMessage(errors, correlationId);
452 const expectedMessage = {
458 expect(window.parent.postMessage).toHaveBeenCalledWith(
460 type: 'chargebee-submit-response',
467 it('should send 3ds success message', () => {
468 const paymentIntent: PaymentIntent = {
469 type: 'payment_intent',
472 const correlationId = 'id-1';
474 messageBus?.send3dsSuccessMessage(
475 paymentIntent as any, // todo: fix types
479 const expectedMessage = {
485 expect(window.parent.postMessage).toHaveBeenCalledWith(
487 type: 'chargebee-submit-response',
494 it('should send unhandled error message', () => {
495 const error = new Error('Unhandled error');
497 messageBus?.sendUnhandledErrorMessage(error);
499 expect(window.parent.postMessage).toHaveBeenCalled();
501 const postMessageArg = (window.parent.postMessage as jest.Mock).mock.calls[0][0];
502 const parsedArg = JSON.parse(postMessageArg);
504 expect(parsedArg).toEqual({
505 type: 'chargebee-unhandled-error',
507 error: expect.objectContaining({
508 message: 'Unhandled error',
511 checkpoints: expect.any(Array),
512 chargebeeWrapperVersion,
517 it('should listen to direct debit submit event', () => {
518 const event: DirectDebitSubmitEvent = {
519 type: 'direct-debit-submit',
520 correlationId: 'dd-123',
525 currency_code: 'USD',
526 gateway_account_id: 'ga_123',
528 customer_id: 'cust_123',
529 payment_method_type: 'card',
530 expires_at: 1234567890,
531 created_at: 1234567890,
532 modified_at: 1234567890,
533 updated_at: 1234567890,
534 resource_version: 1234567890,
535 object: 'payment_intent',
538 email: 'test@example.com',
539 company: 'Test Company',
542 customerNameType: 'individual',
544 addressLine1: '123 Test St',
547 iban: 'DE89370400440532013000',
551 // Mock the onDirectDebitSubmit handler
552 const mockOnDirectDebitSubmit = jest.fn();
553 messageBus!.onDirectDebitSubmit = mockOnDirectDebitSubmit;
557 new MessageEvent('message', {
562 expect(mockOnDirectDebitSubmit).toHaveBeenCalled();
563 const firstArg = mockOnDirectDebitSubmit.mock.calls[0][0];
564 expect(firstArg).toEqual(event);
566 const secondArg = mockOnDirectDebitSubmit.mock.calls[0][1];
567 expect(secondArg).toBeInstanceOf(Function);
569 const response: MessageBusResponse<{}> = {
574 expect(window.parent.postMessage).toHaveBeenCalledWith(
576 type: 'direct-debit-submit-response',
577 correlationId: event.correlationId,