import 'reflect-metadata'; import { ChangeDetectorRef, EventEmitter, } from '@angular/core'; import { StripeElementsComponent, } from './stripe-elements.component'; import { StripeChangeEventInterface, StripeElementsInterface, StripeInterface, StripePaymentVersion, StripeResponseInterface, StripeSingleElementInterface, } from './../../models/index'; import * as mock from './../../mocks/index'; import { HttpClient } from '@angular/common/http'; const initMockHttp = mock.http(jest); const initStripeElementsComponent = ( stripe?: StripeInterface, changeDetectorRef?: ChangeDetectorRef, ) => { return new StripeElementsComponent( stripe, changeDetectorRef, ); }; const MOCK_PAYMENT_INTENT_CLIENT_SECRET = 'client_secret'; describe('defaults', () => { test('Sets a default cardNumberPlaceholder', () => { expect(initStripeElementsComponent().cardNumberPlaceholder).toBe(''); }); test('Sets a default cardExpiryPlaceholder', () => { expect(initStripeElementsComponent().cardExpiryPlaceholder).toBe(''); }); test('Sets a default cardCvcPlaceholder', () => { expect(initStripeElementsComponent().cardCvcPlaceholder).toBe(''); }); test('Sets a default for inputStyling', () => { expect(initStripeElementsComponent().inputStyling).toEqual({ classes: { base: 'c-stripe-elements__stripe-element', empty: 'c-stripe-elements__stripe-element--empty', focus: 'c-stripe-elements__stripe-element--focus', invalid: 'c-stripe-elements__stripe-element--invalid', }, placeholder: '', style: { base: { '::placeholder': { color: '#aab7c4', }, 'color': '#32325d', 'fontFamily': 'sans-serif', 'fontSize': '16px', 'fontSmoothing': 'antialiased', 'fontWeight': 500, }, invalid: { color: '#32325d', }, }, }); }); test('Sets a default submitButtonLabel', () => { expect(initStripeElementsComponent().submitButtonLabel).toBe('Save'); }); test('Sets a default isLoadingExternalData', () => { expect(initStripeElementsComponent().isLoadingExternalData).toBe(false); }); test('Sets a default buttonType', () => { expect(initStripeElementsComponent().buttonType).toBe('button'); }); test('Sets a default onSuccess', () => { expect(initStripeElementsComponent().onSuccess).toEqual( new EventEmitter(), ); }); test('Sets a default onCvcInfoButtonPressed', () => { expect(initStripeElementsComponent().onCvcInfoButtonPressed).toEqual( new EventEmitter(), ); }); test('Sets a default isLoadingStripeData', () => { expect(initStripeElementsComponent().isLoadingStripeData).toBe(false); }); }); describe('get isCvcButtonVisible', () => { test('Returns true if the onCvcInfoButtonPressed has an output', () => { const stripeElementsComponent = initStripeElementsComponent(); stripeElementsComponent.onCvcInfoButtonPressed.observers = { length: 1, } as any; expect(stripeElementsComponent.isCvcButtonVisible).toBe(true); }); test('Returns false if onCvcInfoButtonPressed has no output', () => { const stripeElementsComponent = initStripeElementsComponent(); stripeElementsComponent.onCvcInfoButtonPressed.observers = { length: 0, } as any; expect(stripeElementsComponent.isCvcButtonVisible).toBe(false); }); }); describe('get isCvcButtonVisible', () => { test('Returns true if isLoadingExternalData is true', () => { const stripeElementsComponent = initStripeElementsComponent(); stripeElementsComponent.isLoadingExternalData = true; expect(stripeElementsComponent.isButtonLoading).toBe(true); }); // tslint:disable-next-line test('Returns true if isLoadingExternalData is false but isLoadingStripeData is true', () => { const stripeElementsComponent = initStripeElementsComponent(); stripeElementsComponent.isLoadingExternalData = false; stripeElementsComponent.isLoadingStripeData = true; expect(stripeElementsComponent.isButtonLoading).toBe(true); }); // tslint:disable-next-line test('Returns false if both isLoadingExternalData and isLoadingStripeData is false', () => { const stripeElementsComponent = initStripeElementsComponent(); stripeElementsComponent.isLoadingExternalData = false; stripeElementsComponent.isLoadingStripeData = false; expect(stripeElementsComponent.isButtonLoading).toBe(false); }); }); describe('ngAfterViewInit', () => { const initNgAfterViewInitData = () => { const mockStripeCardNumberElement = {} as StripeSingleElementInterface; const mockStripeCardExpiryElement = {} as StripeSingleElementInterface; const mockStripeCardCvcElement = {} as StripeSingleElementInterface; [ mockStripeCardCvcElement, mockStripeCardExpiryElement, mockStripeCardNumberElement, ].forEach((element) => { element.mount = jest.fn(); element.addEventListener = jest.fn(); }); const stripeElements = { create: jest.fn() .mockReturnValueOnce(mockStripeCardNumberElement) .mockReturnValueOnce(mockStripeCardExpiryElement) .mockReturnValueOnce(mockStripeCardCvcElement), } as StripeElementsInterface; const stripe = {} as StripeInterface; stripe.elements = jest.fn().mockReturnValueOnce(stripeElements); const stripeElementsComponent = initStripeElementsComponent( stripe, ); stripeElementsComponent.cardNumberElement = { nativeElement: {}, }; stripeElementsComponent.cardExpiryElement = { nativeElement: {}, }; stripeElementsComponent.cardCvcElement = { nativeElement: {}, }; stripeElementsComponent.inputStyling = {}; stripeElementsComponent.updateCardNumberError = jest.fn(); stripeElementsComponent.updateCardExpiryError = jest.fn(); stripeElementsComponent.updateCardCvcError = jest.fn(); return { mockStripeCardCvcElement, mockStripeCardExpiryElement, mockStripeCardNumberElement, stripe, stripeElements, stripeElementsComponent, }; }; test('Calls stripe.elements', () => { const { stripe, stripeElementsComponent, } = initNgAfterViewInitData(); stripeElementsComponent.ngAfterViewInit(); expect(stripe.elements).toHaveBeenCalledTimes(1); }); test('Creates the stripe card number', () => { const { stripeElements, stripeElementsComponent, } = initNgAfterViewInitData(); stripeElementsComponent.ngAfterViewInit(); expect(stripeElements.create).toHaveBeenCalledWith( 'cardNumber', stripeElementsComponent.inputStyling, ); }); test('Sets the stripe card number to the mounted element', () => { const { mockStripeCardNumberElement, stripeElementsComponent, } = initNgAfterViewInitData(); stripeElementsComponent.ngAfterViewInit(); expect(stripeElementsComponent.stripeCardNumber).toBe( mockStripeCardNumberElement, ); }); test('Mounts the stripe card number', () => { const { mockStripeCardNumberElement, stripeElementsComponent, } = initNgAfterViewInitData(); stripeElementsComponent.ngAfterViewInit(); expect(mockStripeCardNumberElement.mount).toHaveBeenCalledWith( stripeElementsComponent.cardNumberElement.nativeElement, ); }); test('Adds an event to the stripe card number', () => { const { mockStripeCardNumberElement, stripeElementsComponent, } = initNgAfterViewInitData(); stripeElementsComponent.ngAfterViewInit(); expect(mockStripeCardNumberElement.addEventListener) .toHaveBeenCalledTimes(1); }); // tslint:disable-next-line test('When the stripe card number change event is triggered call updateCardNumberError', () => { const { mockStripeCardNumberElement, stripeElementsComponent, } = initNgAfterViewInitData(); stripeElementsComponent.ngAfterViewInit(); (mockStripeCardNumberElement.addEventListener as any) .mock.calls[0][1]('some-value'); expect(stripeElementsComponent.updateCardNumberError) .toHaveBeenCalledWith('some-value'); }); test('Creates the stripe card expiry', () => { const { stripeElements, stripeElementsComponent, } = initNgAfterViewInitData(); stripeElementsComponent.ngAfterViewInit(); expect(stripeElements.create).toHaveBeenCalledWith( 'cardExpiry', stripeElementsComponent.inputStyling, ); }); test('Sets the stripe card expiry to the mounted element', () => { const { mockStripeCardExpiryElement, stripeElementsComponent, } = initNgAfterViewInitData(); stripeElementsComponent.ngAfterViewInit(); expect(stripeElementsComponent.stripeCardExpiry).toBe( mockStripeCardExpiryElement, ); }); test('Mounts the stripe card expiry', () => { const { mockStripeCardExpiryElement, stripeElementsComponent, } = initNgAfterViewInitData(); stripeElementsComponent.ngAfterViewInit(); expect(mockStripeCardExpiryElement.mount).toHaveBeenCalledWith( stripeElementsComponent.cardNumberElement.nativeElement, ); }); test('Adds an event to the stripe card expiry', () => { const { mockStripeCardExpiryElement, stripeElementsComponent, } = initNgAfterViewInitData(); stripeElementsComponent.ngAfterViewInit(); expect(mockStripeCardExpiryElement.addEventListener) .toHaveBeenCalledTimes(1); }); // tslint:disable-next-line test('When the stripe card expiry change event is triggered call updateCardExpiryError', () => { const { mockStripeCardExpiryElement, stripeElementsComponent, } = initNgAfterViewInitData(); stripeElementsComponent.ngAfterViewInit(); (mockStripeCardExpiryElement.addEventListener as any) .mock.calls[0][1]('some-value'); expect(stripeElementsComponent.updateCardExpiryError) .toHaveBeenCalledWith('some-value'); }); test('Creates the stripe card cvc', () => { const { stripeElements, stripeElementsComponent, } = initNgAfterViewInitData(); stripeElementsComponent.ngAfterViewInit(); expect(stripeElements.create).toHaveBeenCalledWith( 'cardCvc', stripeElementsComponent.inputStyling, ); }); test('Sets the stripe card cvc to the mounted element', () => { const { mockStripeCardCvcElement, stripeElementsComponent, } = initNgAfterViewInitData(); stripeElementsComponent.ngAfterViewInit(); expect(stripeElementsComponent.stripeCardCvc).toBe( mockStripeCardCvcElement, ); }); test('Mounts the stripe card cvc', () => { const { mockStripeCardCvcElement, stripeElementsComponent, } = initNgAfterViewInitData(); stripeElementsComponent.ngAfterViewInit(); expect(mockStripeCardCvcElement.mount).toHaveBeenCalledWith( stripeElementsComponent.cardNumberElement.nativeElement, ); }); test('Adds an event to the stripe card cvc', () => { const { mockStripeCardCvcElement, stripeElementsComponent, } = initNgAfterViewInitData(); stripeElementsComponent.ngAfterViewInit(); expect(mockStripeCardCvcElement.addEventListener) .toHaveBeenCalledTimes(1); }); // tslint:disable-next-line test('When the stripe card cvc change event is triggered call updateCardCvcError', () => { const { mockStripeCardCvcElement, stripeElementsComponent, } = initNgAfterViewInitData(); stripeElementsComponent.ngAfterViewInit(); (mockStripeCardCvcElement.addEventListener as any) .mock.calls[0][1]('some-value'); expect(stripeElementsComponent.updateCardCvcError) .toHaveBeenCalledWith('some-value'); }); }); describe('ngOnDestroy', () => { const initNgOnDestroyData = () => { const stripeElementsComponent = initStripeElementsComponent(); stripeElementsComponent.stripeCardNumber = {} as StripeSingleElementInterface; stripeElementsComponent.stripeCardExpiry = {} as StripeSingleElementInterface; stripeElementsComponent.stripeCardCvc = {} as StripeSingleElementInterface; [ stripeElementsComponent.stripeCardNumber, stripeElementsComponent.stripeCardExpiry, stripeElementsComponent.stripeCardCvc, ].forEach((stripeElement) => { stripeElement.removeEventListener = jest.fn(); stripeElement.destroy = jest.fn(); }); return { stripeElementsComponent, }; }; test('Calls removeEventListener for on stripeCardNumber', () => { const { stripeElementsComponent, } = initNgOnDestroyData(); stripeElementsComponent.ngOnDestroy(); expect(stripeElementsComponent.stripeCardNumber.removeEventListener) .toHaveBeenCalledWith('change'); }); test('Calls removeEventListener for on stripeCardExpiry', () => { const { stripeElementsComponent, } = initNgOnDestroyData(); stripeElementsComponent.ngOnDestroy(); expect(stripeElementsComponent.stripeCardExpiry.removeEventListener) .toHaveBeenCalledWith('change'); }); test('Calls removeEventListener for on stripeCardCvc', () => { const { stripeElementsComponent, } = initNgOnDestroyData(); stripeElementsComponent.ngOnDestroy(); expect(stripeElementsComponent.stripeCardCvc.removeEventListener) .toHaveBeenCalledWith('change'); }); test('Calls destroy on stripeCardNumber', () => { const { stripeElementsComponent, } = initNgOnDestroyData(); stripeElementsComponent.ngOnDestroy(); expect(stripeElementsComponent.stripeCardNumber.destroy) .toHaveBeenCalledTimes(1); }); test('Calls destroy on stripeCardExpiry', () => { const { stripeElementsComponent, } = initNgOnDestroyData(); stripeElementsComponent.ngOnDestroy(); expect(stripeElementsComponent.stripeCardExpiry.destroy) .toHaveBeenCalledTimes(1); }); test('Calls destroy on stripeCardCvc', () => { const { stripeElementsComponent, } = initNgOnDestroyData(); stripeElementsComponent.ngOnDestroy(); expect(stripeElementsComponent.stripeCardCvc.destroy) .toHaveBeenCalledTimes(1); }); }); describe('updateCardNumberError', () => { const runUpdateCardNumberError = ({ mockStripeChangeEvent = { error: { message: 'some-message', }, } as StripeChangeEventInterface, }: { mockStripeChangeEvent?: StripeChangeEventInterface, } = {}) => { const changeDetectorRef = {} as ChangeDetectorRef; changeDetectorRef.markForCheck = jest.fn(); const stripeElementsComponent = initStripeElementsComponent( undefined, changeDetectorRef, ); stripeElementsComponent.updateCardNumberError(mockStripeChangeEvent); return { changeDetectorRef, stripeElementsComponent, }; }; test('Sets cardNumberError to undefined if the error is undefined', () => { const { stripeElementsComponent, } = runUpdateCardNumberError({ mockStripeChangeEvent: {}, }); expect(stripeElementsComponent.cardNumberError).toBeUndefined(); }); // tslint:disable-next-line test('Sets cardNumberError to the the error from the event if defined', () => { const { stripeElementsComponent, } = runUpdateCardNumberError(); expect(stripeElementsComponent.cardNumberError).toBe('some-message'); }); // tslint:disable-next-line test('Marks the component for change detection', () => { const { changeDetectorRef, } = runUpdateCardNumberError(); expect(changeDetectorRef.markForCheck).toHaveBeenCalled(); }); }); describe('updateCardExpiryError', () => { const runUpdateCardExpiryError = ({ mockStripeChangeEvent = { error: { message: 'some-message', }, } as StripeChangeEventInterface, }: { mockStripeChangeEvent?: StripeChangeEventInterface, } = {}) => { const changeDetectorRef = {} as ChangeDetectorRef; changeDetectorRef.markForCheck = jest.fn(); const stripeElementsComponent = initStripeElementsComponent( undefined, changeDetectorRef, ); stripeElementsComponent.updateCardExpiryError(mockStripeChangeEvent); return { changeDetectorRef, stripeElementsComponent, }; }; test('Sets cardExpiryError to undefined if the error is undefined', () => { const { stripeElementsComponent, } = runUpdateCardExpiryError({ mockStripeChangeEvent: {}, }); expect(stripeElementsComponent.cardExpiryError).toBeUndefined(); }); // tslint:disable-next-line test('Sets cardExpiryError to the the error from the event if defined', () => { const { stripeElementsComponent, } = runUpdateCardExpiryError(); expect(stripeElementsComponent.cardExpiryError).toBe('some-message'); }); // tslint:disable-next-line test('Marks the component for change detection', () => { const { changeDetectorRef, } = runUpdateCardExpiryError(); expect(changeDetectorRef.markForCheck).toHaveBeenCalled(); }); }); describe('updateCardCvcError', () => { const runUpdateCardCvcError = ({ mockStripeChangeEvent = { error: { message: 'some-message', }, } as StripeChangeEventInterface, }: { mockStripeChangeEvent?: StripeChangeEventInterface, } = {}) => { const changeDetectorRef = {} as ChangeDetectorRef; changeDetectorRef.markForCheck = jest.fn(); const stripeElementsComponent = initStripeElementsComponent( undefined, changeDetectorRef, ); stripeElementsComponent.updateCardCvcError(mockStripeChangeEvent); return { changeDetectorRef, stripeElementsComponent, }; }; test('Sets cardCvcError to undefined if the error is undefined', () => { const { stripeElementsComponent, } = runUpdateCardCvcError({ mockStripeChangeEvent: {}, }); expect(stripeElementsComponent.cardCvcError).toBeUndefined(); }); // tslint:disable-next-line test('Sets cardCvcError to the the error from the event if defined', () => { const { stripeElementsComponent, } = runUpdateCardCvcError(); expect(stripeElementsComponent.cardCvcError).toBe('some-message'); }); // tslint:disable-next-line test('Marks the component for change detection', () => { const { changeDetectorRef, } = runUpdateCardCvcError(); expect(changeDetectorRef.markForCheck).toHaveBeenCalled(); }); }); describe('onSubmit', () => { const initOnSubmitData = ({ mockTokenResponse = new Promise( (resolve) => resolve({ token: { id: 'tokenId', }, }), ), }: { mockTokenResponse?: Promise, } = {}) => { const changeDetectorRef = {} as ChangeDetectorRef; changeDetectorRef.markForCheck = jest.fn(); const stripe = {} as StripeInterface; stripe.createToken = jest.fn().mockReturnValue(mockTokenResponse); const stripeElementsComponent = initStripeElementsComponent( stripe, changeDetectorRef, ); stripeElementsComponent.stripeCardNumber = {} as StripeSingleElementInterface; stripeElementsComponent.onSuccess.emit = jest.fn(); stripeElementsComponent.onCardDeclined.emit = jest.fn(); return { changeDetectorRef, stripe, stripeElementsComponent, }; }; test('Sets isLoadingStripeData to true', () => { const { stripeElementsComponent, } = initOnSubmitData({ mockTokenResponse: new Promise(() => undefined), }); stripeElementsComponent.processStripePaymentV1(); expect(stripeElementsComponent.isLoadingStripeData).toBe(true); }); test('Marks the component for change detection', () => { const { changeDetectorRef, stripeElementsComponent, } = initOnSubmitData({ mockTokenResponse: new Promise(() => undefined), }); stripeElementsComponent.processStripePaymentV1(); expect(changeDetectorRef.markForCheck).toHaveBeenCalledTimes(1); }); test('Calls stripe.createToken with the stripeCardNumber', () => { const { stripeElementsComponent, stripe, } = initOnSubmitData(); stripeElementsComponent.processStripePaymentV1(); expect(stripe.createToken).toHaveBeenCalledWith( stripeElementsComponent.stripeCardNumber, ); }); test('Emits the token id to onSuccess if it exists', async () => { const { stripeElementsComponent, } = initOnSubmitData(); await stripeElementsComponent.processStripePaymentV1(); expect(stripeElementsComponent.onSuccess.emit) .toHaveBeenCalledWith('tokenId'); }); // tslint:disable-next-line test('Does not emit to onSuccess if the response contains no token', async () => { const { stripeElementsComponent, } = initOnSubmitData({ mockTokenResponse: new Promise( (resolve) => resolve({}), ), }); await stripeElementsComponent.processStripePaymentV1(); expect(stripeElementsComponent.onSuccess.emit).not.toHaveBeenCalled(); }); // tslint:disable-next-line test('Emits to onCardDeclined if the response contains an error with code card_declined', async () => { const { stripeElementsComponent, } = initOnSubmitData({ mockTokenResponse: new Promise( (resolve) => resolve({ error: { code: 'card_declined', message: 'some message', }, } as StripeResponseInterface), ), }); await stripeElementsComponent.processStripePaymentV1(); expect(stripeElementsComponent.onCardDeclined.emit) .toHaveBeenCalledWith('some message'); }); // tslint:disable-next-line test('Does not emit to onCardDeclined if the response contains an error without code card_declined', async () => { const { stripeElementsComponent, } = initOnSubmitData({ mockTokenResponse: new Promise( (resolve) => resolve({ error: { code: 'some-other-code', message: 'some message', }, } as StripeResponseInterface), ), }); await stripeElementsComponent.processStripePaymentV1(); expect(stripeElementsComponent.onCardDeclined.emit).not.toBeCalled(); }); // tslint:disable-next-line test('Sets isLoadingStripeData to false after stripe.create token has completed', async () => { const { stripeElementsComponent, } = initOnSubmitData(); await stripeElementsComponent.processStripePaymentV1(); expect(stripeElementsComponent.isLoadingStripeData).toBe(false); }); // tslint:disable-next-line test('Marks the component for change detection a second time after the stripe token has finished loading', async () => { const { changeDetectorRef, stripeElementsComponent, } = initOnSubmitData(); await stripeElementsComponent.processStripePaymentV1(); expect(changeDetectorRef.markForCheck).toHaveBeenCalledTimes(2); }); test(`given default StripePaymentVersion, when submitting, then 'processStripePaymentV2' should be called`, () => { const { stripeElementsComponent, } = initOnSubmitData(); stripeElementsComponent.processStripePaymentV2 = jest.fn(); stripeElementsComponent.onSubmit(); expect(stripeElementsComponent.processStripePaymentV2).toHaveBeenCalled(); }); test(`given StripePaymentVersion 'V1', when submitting, then 'createToken' should be called`, () => { const createToken = jest.fn(() => ({ then: jest.fn })); const stripeMock = { createToken } as unknown as StripeInterface; const changeDetectorRef = { markForCheck: jest.fn() } as unknown as ChangeDetectorRef; const sut = initStripeElementsComponent(stripeMock, changeDetectorRef); sut.version = StripePaymentVersion.V1; sut.onSubmit(); expect(createToken).toHaveBeenCalled(); }); test(`given StripePaymentVersion equal 'undefined', when submitting, then exception should be raised`, () => { const sut = initStripeElementsComponent({} as StripeInterface, {} as ChangeDetectorRef); sut.version = undefined; expect(() => sut.onSubmit()).toThrowError('StripePaymentVersion undefined is invalid'); }); }); describe('cvcInfoButtonPressed', () => { test('Emits an event to onCvcInfoButtonPressed', () => { const stripeElementsComponent = initStripeElementsComponent(); stripeElementsComponent.onCvcInfoButtonPressed.emit = jest.fn(); stripeElementsComponent.cvcInfoButtonPressed(); expect(stripeElementsComponent.onCvcInfoButtonPressed.emit) .toHaveBeenCalled(); }); }); describe('processStripePaymentV2', () => { const initProcessStripePaymentV2Data = () => { const changeDetectorRef = {} as ChangeDetectorRef; changeDetectorRef.markForCheck = jest.fn(); const stripe = {} as StripeInterface; const stripeElementsComponent = initStripeElementsComponent( stripe, changeDetectorRef, ); stripeElementsComponent.stripeCardNumber = {} as StripeSingleElementInterface; stripeElementsComponent.onSuccess.emit = jest.fn(); stripeElementsComponent.onCardDeclined.emit = jest.fn(); stripeElementsComponent.paymentIntentClientSecret = MOCK_PAYMENT_INTENT_CLIENT_SECRET; return { changeDetectorRef, stripe, stripeElementsComponent, }; }; test(`Given a payment intent client secret was not provided, when processStripePaymentV2 is called, then onPaymentError is called`, () => { const { stripeElementsComponent, } = initProcessStripePaymentV2Data(); stripeElementsComponent.paymentIntentClientSecret = undefined; stripeElementsComponent.onPaymentError = jest.fn(); stripeElementsComponent.processStripePaymentV2(); // tslint:disable-next-line expect(stripeElementsComponent.onPaymentError).toHaveBeenCalled(); }); test('Given confirmCardPaymentV2 is called, StripeJS confirmCardPayment is called with payment intent client_secret and card info', () => { const { stripe, stripeElementsComponent, } = initProcessStripePaymentV2Data(); stripe.confirmCardPayment = jest.fn(); stripeElementsComponent.confirmCardPaymentV2(); expect(stripe.confirmCardPayment).toHaveBeenCalledWith(stripeElementsComponent.paymentIntentClientSecret, { payment_method: { card: {}, }, }); }); test(`Given StripeJS confirmCardPayment is called, when the result is successful then onSuccess.emit should be called`, async () => { const { stripe, stripeElementsComponent, } = initProcessStripePaymentV2Data(); stripe.confirmCardPayment = jest.fn().mockReturnValue(new Promise( (resolve) => resolve({}), )); await stripeElementsComponent.confirmCardPaymentV2(); expect(stripeElementsComponent.onSuccess.emit).toHaveBeenCalled(); }); test(`Given StripeJS confirmCardPayment is called, when the result is an error then onPaymentError should be called with the error`, async () => { const { stripe, stripeElementsComponent, } = initProcessStripePaymentV2Data(); stripe.confirmCardPayment = jest.fn().mockReturnValue(new Promise( (resolve) => resolve({ error: { message: 'Test error', }, }), )); stripeElementsComponent.onPaymentError = jest.fn(); await stripeElementsComponent.confirmCardPaymentV2(); expect(stripeElementsComponent.onPaymentError).toHaveBeenCalledWith({ message: 'Test error', }); }); // tslint:disable-next-line test(`Given confirmCardPaymentV2 is called, when the request to StripeJS confirmCardPayment fails, then onPaymentError should be called with the error`, async () => { const { stripe, stripeElementsComponent, } = initProcessStripePaymentV2Data(); stripe.confirmCardPayment = jest.fn().mockReturnValue(new Promise( (resolve, reject) => reject({ error: { message: 'Test error', }, }), )); stripeElementsComponent.onPaymentError = jest.fn(); await stripeElementsComponent.confirmCardPaymentV2(); expect(stripeElementsComponent.onPaymentError).toHaveBeenCalledWith({ error: { message: 'Test error', }, }); }); test('Given onPaymentError is called, onCardDeclined.emit should be called and loading status should be set to inital state', () => { const { stripeElementsComponent, } = initProcessStripePaymentV2Data(); stripeElementsComponent.updatePaymentStatus = jest.fn(); stripeElementsComponent.onPaymentError({ message: 'Test error', }); expect(stripeElementsComponent.onCardDeclined.emit).toHaveBeenCalledWith('Test error'); expect(stripeElementsComponent.updatePaymentStatus).toHaveBeenCalledWith(false); }); });